wps_attr_build.c revision 1e78e76961664775f58b139f8c6388cfa0485f3d
1c5707112e7635d1dd2f2cc9c4f42e79a51302ccaJia Liu/* 2090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola * Wi-Fi Protected Setup - attribute building 3090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola * Copyright (c) 2008, Jouni Malinen <j@w1.fi> 4090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola * 5090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola * This software may be distributed under the terms of the BSD license. 6090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola * See README for more details. 7090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola */ 8090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 9090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "includes.h" 1037ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 11090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "common.h" 12090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "crypto/aes_wrap.h" 1337ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka#include "crypto/crypto.h" 14090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "crypto/dh_group5.h" 15090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "crypto/sha256.h" 16090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "crypto/random.h" 17090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "common/ieee802_11_defs.h" 18090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "wps_i.h" 1937ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 20090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 21090445967f0b5988446faffefd1d0722f982bc7aRafael Espindolaint wps_build_public_key(struct wps_data *wps, struct wpabuf *msg) 22090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola{ 23090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola struct wpabuf *pubkey; 24090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 25090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpa_printf(MSG_DEBUG, "WPS: * Public Key"); 26b889e0cd2fea4afee623d5be603b912b955a2ecaAkira Hatanaka wpabuf_free(wps->dh_privkey); 27b889e0cd2fea4afee623d5be603b912b955a2ecaAkira Hatanaka wps->dh_privkey = NULL; 28090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey && 29090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wps->wps->dh_ctx) { 30090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys"); 3136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (wps->wps->dh_pubkey == NULL) { 3236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines wpa_printf(MSG_DEBUG, 3336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "WPS: wps->wps->dh_pubkey == NULL"); 34090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola return -1; 35090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola } 36090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey); 3793ee286e8d949147f8df7f093c9bd8529a99102dJack Carter wps->dh_ctx = wps->wps->dh_ctx; 38b889e0cd2fea4afee623d5be603b912b955a2ecaAkira Hatanaka wps->wps->dh_ctx = NULL; 39a551a48402385cf3f4b754dc72264b2f0974b1a6Akira Hatanaka pubkey = wpabuf_dup(wps->wps->dh_pubkey); 40101771ba4d9c2421f836069fcedf9ddc8a0c9dc7Jack Carter#ifdef CONFIG_WPS_NFC 4193ee286e8d949147f8df7f093c9bd8529a99102dJack Carter } else if (wps->dev_pw_id >= 0x10 && wps->wps->ap && 42090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id) { 43090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpa_printf(MSG_DEBUG, "WPS: Using NFC password token DH keys"); 44090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola if (wps->wps->ap_nfc_dh_privkey == NULL) { 45090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpa_printf(MSG_DEBUG, 46090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola "WPS: wps->wps->ap_nfc_dh_privkey == NULL"); 4736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return -1; 48090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola } 49090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola if (wps->wps->ap_nfc_dh_pubkey == NULL) { 50090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpa_printf(MSG_DEBUG, 51090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola "WPS: wps->wps->ap_nfc_dh_pubkey == NULL"); 52090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola return -1; 53090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola } 54090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wps->dh_privkey = wpabuf_dup(wps->wps->ap_nfc_dh_privkey); 55090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola pubkey = wpabuf_dup(wps->wps->ap_nfc_dh_pubkey); 56090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, pubkey); 57090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#endif /* CONFIG_WPS_NFC */ 58e2245bab3ca29dc2142d8f254005f4ae7c40cde2Jack Carter } else { 59e2245bab3ca29dc2142d8f254005f4ae7c40cde2Jack Carter wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys"); 60e2245bab3ca29dc2142d8f254005f4ae7c40cde2Jack Carter dh5_free(wps->dh_ctx); 61090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wps->dh_ctx = dh5_init(&wps->dh_privkey, &pubkey); 62096d617796228293810cb0443c6617b33c5afdc5Jack Carter pubkey = wpabuf_zeropad(pubkey, 192); 63096d617796228293810cb0443c6617b33c5afdc5Jack Carter } 64096d617796228293810cb0443c6617b33c5afdc5Jack Carter if (wps->dh_ctx == NULL || wps->dh_privkey == NULL || pubkey == NULL) { 65096d617796228293810cb0443c6617b33c5afdc5Jack Carter wpa_printf(MSG_DEBUG, "WPS: Failed to initialize " 66096d617796228293810cb0443c6617b33c5afdc5Jack Carter "Diffie-Hellman handshake"); 67096d617796228293810cb0443c6617b33c5afdc5Jack Carter wpabuf_free(pubkey); 68096d617796228293810cb0443c6617b33c5afdc5Jack Carter return -1; 69090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola } 70090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); 71090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpa_hexdump_buf(MSG_DEBUG, "WPS: DH own Public Key", pubkey); 72090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 73090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpabuf_put_be16(msg, ATTR_PUBLIC_KEY); 74090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpabuf_put_be16(msg, wpabuf_len(pubkey)); 75090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpabuf_put_buf(msg, pubkey); 76090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 77090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola if (wps->registrar) { 78090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpabuf_free(wps->dh_pubkey_r); 79090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wps->dh_pubkey_r = pubkey; 80090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola } else { 81090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpabuf_free(wps->dh_pubkey_e); 82090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wps->dh_pubkey_e = pubkey; 83090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola } 84090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 85090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola return 0; 86090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola} 87090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 88090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 89090445967f0b5988446faffefd1d0722f982bc7aRafael Espindolaint wps_build_req_type(struct wpabuf *msg, enum wps_request_type type) 90090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola{ 91090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpa_printf(MSG_DEBUG, "WPS: * Request Type"); 92090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpabuf_put_be16(msg, ATTR_REQUEST_TYPE); 93090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpabuf_put_be16(msg, 1); 94090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpabuf_put_u8(msg, type); 95090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola return 0; 96090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola} 97090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 98090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 99090445967f0b5988446faffefd1d0722f982bc7aRafael Espindolaint wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type) 100090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola{ 101090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpa_printf(MSG_DEBUG, "WPS: * Response Type (%d)", type); 102090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpabuf_put_be16(msg, ATTR_RESPONSE_TYPE); 103090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpabuf_put_be16(msg, 1); 104090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpabuf_put_u8(msg, type); 105090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola return 0; 106090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola} 107090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 108090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 109090445967f0b5988446faffefd1d0722f982bc7aRafael Espindolaint wps_build_config_methods(struct wpabuf *msg, u16 methods) 110090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola{ 111090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); 112090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpabuf_put_be16(msg, ATTR_CONFIG_METHODS); 113090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola wpabuf_put_be16(msg, 2); 1140140e55393c4403ab240c386501cdc5e438dcc0eJack Carter wpabuf_put_be16(msg, methods); 1150140e55393c4403ab240c386501cdc5e438dcc0eJack Carter return 0; 1160140e55393c4403ab240c386501cdc5e438dcc0eJack Carter} 1170140e55393c4403ab240c386501cdc5e438dcc0eJack Carter 1180140e55393c4403ab240c386501cdc5e438dcc0eJack Carter 1190140e55393c4403ab240c386501cdc5e438dcc0eJack Carterint wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid) 120fd506efec628819f7e6fad8016a9dbb5d8612b8bJack Carter{ 121fd506efec628819f7e6fad8016a9dbb5d8612b8bJack Carter wpa_printf(MSG_DEBUG, "WPS: * UUID-E"); 122fd506efec628819f7e6fad8016a9dbb5d8612b8bJack Carter wpabuf_put_be16(msg, ATTR_UUID_E); 1230140e55393c4403ab240c386501cdc5e438dcc0eJack Carter wpabuf_put_be16(msg, WPS_UUID_LEN); 1240140e55393c4403ab240c386501cdc5e438dcc0eJack Carter wpabuf_put_data(msg, uuid, WPS_UUID_LEN); 1250140e55393c4403ab240c386501cdc5e438dcc0eJack Carter return 0; 1260140e55393c4403ab240c386501cdc5e438dcc0eJack Carter} 1270140e55393c4403ab240c386501cdc5e438dcc0eJack Carter 1280140e55393c4403ab240c386501cdc5e438dcc0eJack Carter 1290140e55393c4403ab240c386501cdc5e438dcc0eJack Carterint wps_build_dev_password_id(struct wpabuf *msg, u16 id) 1300140e55393c4403ab240c386501cdc5e438dcc0eJack Carter{ 1310140e55393c4403ab240c386501cdc5e438dcc0eJack Carter wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id); 1320140e55393c4403ab240c386501cdc5e438dcc0eJack Carter wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); 133fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter wpabuf_put_be16(msg, 2); 134fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter wpabuf_put_be16(msg, id); 135fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter return 0; 136fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter} 137fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter 138fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter 139198ad916d736047f8a439f19dee25cee917df8a9Jack Carterint wps_build_config_error(struct wpabuf *msg, u16 err) 140198ad916d736047f8a439f19dee25cee917df8a9Jack Carter{ 141198ad916d736047f8a439f19dee25cee917df8a9Jack Carter wpa_printf(MSG_DEBUG, "WPS: * Configuration Error (%d)", err); 142198ad916d736047f8a439f19dee25cee917df8a9Jack Carter wpabuf_put_be16(msg, ATTR_CONFIG_ERROR); 143198ad916d736047f8a439f19dee25cee917df8a9Jack Carter wpabuf_put_be16(msg, 2); 144198ad916d736047f8a439f19dee25cee917df8a9Jack Carter wpabuf_put_be16(msg, err); 145198ad916d736047f8a439f19dee25cee917df8a9Jack Carter return 0; 146198ad916d736047f8a439f19dee25cee917df8a9Jack Carter} 147198ad916d736047f8a439f19dee25cee917df8a9Jack Carter 148198ad916d736047f8a439f19dee25cee917df8a9Jack Carter 149198ad916d736047f8a439f19dee25cee917df8a9Jack Carterint wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg) 150198ad916d736047f8a439f19dee25cee917df8a9Jack Carter{ 1511aaf43c2a2ec0fd4c8dbfe56558237219c5f8af7Zoran Jovanovic u8 hash[SHA256_MAC_LEN]; 1521aaf43c2a2ec0fd4c8dbfe56558237219c5f8af7Zoran Jovanovic const u8 *addr[2]; 1531aaf43c2a2ec0fd4c8dbfe56558237219c5f8af7Zoran Jovanovic size_t len[2]; 1540082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic 1550082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic if (wps->last_msg == NULL) { 1560082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic wpa_printf(MSG_DEBUG, "WPS: Last message not available for " 1570082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic "building authenticator"); 1580082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic return -1; 1590082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic } 1600082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic 1610082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*) 1620082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic * (M_curr* is M_curr without the Authenticator attribute) 1635c042162beb3c2dd556e00aab84c4278a69cd5b1Zoran Jovanovic */ 1645c042162beb3c2dd556e00aab84c4278a69cd5b1Zoran Jovanovic addr[0] = wpabuf_head(wps->last_msg); 1655c042162beb3c2dd556e00aab84c4278a69cd5b1Zoran Jovanovic len[0] = wpabuf_len(wps->last_msg); 1660082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic addr[1] = wpabuf_head(msg); 1670082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic len[1] = wpabuf_len(msg); 1680082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash); 1690082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic 1700082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic wpa_printf(MSG_DEBUG, "WPS: * Authenticator"); 1710082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic wpabuf_put_be16(msg, ATTR_AUTHENTICATOR); 1720082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic wpabuf_put_be16(msg, WPS_AUTHENTICATOR_LEN); 1730082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic wpabuf_put_data(msg, hash, WPS_AUTHENTICATOR_LEN); 1740082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic 1750082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic return 0; 1760082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic} 1770082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic 17836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 17936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesint wps_build_version(struct wpabuf *msg) 18036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 18136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines /* 18236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * Note: This attribute is deprecated and set to hardcoded 0x10 for 18336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines * backwards compatibility reasons. The real version negotiation is 1840082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic * done with Version2. 1850082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic */ 1860082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic wpa_printf(MSG_DEBUG, "WPS: * Version (hardcoded 0x10)"); 1870082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic wpabuf_put_be16(msg, ATTR_VERSION); 1880082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic wpabuf_put_be16(msg, 1); 1890082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic wpabuf_put_u8(msg, 0x10); 1900082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic return 0; 1910082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic} 1920082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic 1930082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic 1940082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovicint wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll, 1950082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic const u8 *auth_macs, size_t auth_macs_count) 196cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines{ 197cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#ifdef CONFIG_WPS2 198cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines u8 *len; 199cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 200cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines wpabuf_put_be16(msg, ATTR_VENDOR_EXT); 201cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines len = wpabuf_put(msg, 2); /* to be filled */ 202dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines wpabuf_put_be24(msg, WPS_VENDOR_ID_WFA); 203dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 204dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines wpa_printf(MSG_DEBUG, "WPS: * Version2 (0x%x)", WPS_VERSION); 205dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines wpabuf_put_u8(msg, WFA_ELEM_VERSION2); 206dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines wpabuf_put_u8(msg, 1); 207dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines wpabuf_put_u8(msg, WPS_VERSION); 208dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 209dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (req_to_enroll) { 210dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines wpa_printf(MSG_DEBUG, "WPS: * Request to Enroll (1)"); 211dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines wpabuf_put_u8(msg, WFA_ELEM_REQUEST_TO_ENROLL); 212dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines wpabuf_put_u8(msg, 1); 213dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines wpabuf_put_u8(msg, 1); 214090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola } 215090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola 216090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola if (auth_macs && auth_macs_count) { 217090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola size_t i; 21836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines wpa_printf(MSG_DEBUG, "WPS: * AuthorizedMACs (count=%d)", 21936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines (int) auth_macs_count); 22036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines wpabuf_put_u8(msg, WFA_ELEM_AUTHORIZEDMACS); 22136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines wpabuf_put_u8(msg, auth_macs_count * ETH_ALEN); 22236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines wpabuf_put_data(msg, auth_macs, auth_macs_count * ETH_ALEN); 22336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (i = 0; i < auth_macs_count; i++) 22436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines wpa_printf(MSG_DEBUG, "WPS: AuthorizedMAC: " MACSTR, 22536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines MAC2STR(&auth_macs[i * ETH_ALEN])); 22636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 22736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 22836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines WPA_PUT_BE16(len, (u8 *) wpabuf_put(msg, 0) - len - 2); 22936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#endif /* CONFIG_WPS2 */ 23036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 23136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#ifdef CONFIG_WPS_TESTING 23236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (WPS_VERSION > 0x20) { 23336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines wpa_printf(MSG_DEBUG, "WPS: * Extensibility Testing - extra " 23436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines "attribute"); 23536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines wpabuf_put_be16(msg, ATTR_EXTENSIBILITY_TEST); 23636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines wpabuf_put_be16(msg, 1); 23736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines wpabuf_put_u8(msg, 42); 23836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 23936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#endif /* CONFIG_WPS_TESTING */ 24036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return 0; 24136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 24236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 24336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 24436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesint wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type) 24536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines{ 24636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines wpa_printf(MSG_DEBUG, "WPS: * Message Type (%d)", msg_type); 24736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines wpabuf_put_be16(msg, ATTR_MSG_TYPE); 24836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines wpabuf_put_be16(msg, 1); 24937ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka wpabuf_put_u8(msg, msg_type); 25037ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka return 0; 25137ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka} 25237ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka 253a551a48402385cf3f4b754dc72264b2f0974b1a6Akira Hatanaka 254a551a48402385cf3f4b754dc72264b2f0974b1a6Akira Hatanakaint wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg) 255a551a48402385cf3f4b754dc72264b2f0974b1a6Akira Hatanaka{ 256a551a48402385cf3f4b754dc72264b2f0974b1a6Akira Hatanaka wpa_printf(MSG_DEBUG, "WPS: * Enrollee Nonce"); 25793ee286e8d949147f8df7f093c9bd8529a99102dJack Carter wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE); 258b889e0cd2fea4afee623d5be603b912b955a2ecaAkira Hatanaka wpabuf_put_be16(msg, WPS_NONCE_LEN); 259b889e0cd2fea4afee623d5be603b912b955a2ecaAkira Hatanaka wpabuf_put_data(msg, wps->nonce_e, WPS_NONCE_LEN); 260090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola return 0; 261090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola} 262 263 264int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg) 265{ 266 wpa_printf(MSG_DEBUG, "WPS: * Registrar Nonce"); 267 wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE); 268 wpabuf_put_be16(msg, WPS_NONCE_LEN); 269 wpabuf_put_data(msg, wps->nonce_r, WPS_NONCE_LEN); 270 return 0; 271} 272 273 274int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg) 275{ 276 u16 auth_types = WPS_AUTH_TYPES; 277#ifdef CONFIG_WPS2 278 auth_types &= ~WPS_AUTH_SHARED; 279#endif /* CONFIG_WPS2 */ 280 wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags"); 281 wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS); 282 wpabuf_put_be16(msg, 2); 283 wpabuf_put_be16(msg, auth_types); 284 return 0; 285} 286 287 288int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg) 289{ 290 u16 encr_types = WPS_ENCR_TYPES; 291#ifdef CONFIG_WPS2 292 encr_types &= ~WPS_ENCR_WEP; 293#endif /* CONFIG_WPS2 */ 294 wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags"); 295 wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS); 296 wpabuf_put_be16(msg, 2); 297 wpabuf_put_be16(msg, encr_types); 298 return 0; 299} 300 301 302int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg) 303{ 304 wpa_printf(MSG_DEBUG, "WPS: * Connection Type Flags"); 305 wpabuf_put_be16(msg, ATTR_CONN_TYPE_FLAGS); 306 wpabuf_put_be16(msg, 1); 307 wpabuf_put_u8(msg, WPS_CONN_ESS); 308 return 0; 309} 310 311 312int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg) 313{ 314 wpa_printf(MSG_DEBUG, "WPS: * Association State"); 315 wpabuf_put_be16(msg, ATTR_ASSOC_STATE); 316 wpabuf_put_be16(msg, 2); 317 wpabuf_put_be16(msg, WPS_ASSOC_NOT_ASSOC); 318 return 0; 319} 320 321 322int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg) 323{ 324 u8 hash[SHA256_MAC_LEN]; 325 326 wpa_printf(MSG_DEBUG, "WPS: * Key Wrap Authenticator"); 327 hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg), 328 wpabuf_len(msg), hash); 329 330 wpabuf_put_be16(msg, ATTR_KEY_WRAP_AUTH); 331 wpabuf_put_be16(msg, WPS_KWA_LEN); 332 wpabuf_put_data(msg, hash, WPS_KWA_LEN); 333 return 0; 334} 335 336 337int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, 338 struct wpabuf *plain) 339{ 340 size_t pad_len; 341 const size_t block_size = 16; 342 u8 *iv, *data; 343 344 wpa_printf(MSG_DEBUG, "WPS: * Encrypted Settings"); 345 346 /* PKCS#5 v2.0 pad */ 347 pad_len = block_size - wpabuf_len(plain) % block_size; 348 os_memset(wpabuf_put(plain, pad_len), pad_len, pad_len); 349 350 wpabuf_put_be16(msg, ATTR_ENCR_SETTINGS); 351 wpabuf_put_be16(msg, block_size + wpabuf_len(plain)); 352 353 iv = wpabuf_put(msg, block_size); 354 if (random_get_bytes(iv, block_size) < 0) 355 return -1; 356 357 data = wpabuf_put(msg, 0); 358 wpabuf_put_buf(msg, plain); 359 if (aes_128_cbc_encrypt(wps->keywrapkey, iv, data, wpabuf_len(plain))) 360 return -1; 361 362 return 0; 363} 364 365 366#ifdef CONFIG_WPS_OOB 367int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id, 368 const struct wpabuf *pubkey, const u8 *dev_pw, 369 size_t dev_pw_len) 370{ 371 size_t hash_len; 372 const u8 *addr[1]; 373 u8 pubkey_hash[WPS_HASH_LEN]; 374 375 addr[0] = wpabuf_head(pubkey); 376 hash_len = wpabuf_len(pubkey); 377 sha256_vector(1, addr, &hash_len, pubkey_hash); 378 379 wpabuf_put_be16(msg, ATTR_OOB_DEVICE_PASSWORD); 380 wpabuf_put_be16(msg, WPS_OOB_PUBKEY_HASH_LEN + 2 + dev_pw_len); 381 wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); 382 wpabuf_put_be16(msg, dev_pw_id); 383 wpabuf_put_data(msg, dev_pw, dev_pw_len); 384 385 return 0; 386} 387#endif /* CONFIG_WPS_OOB */ 388 389 390/* Encapsulate WPS IE data with one (or more, if needed) IE headers */ 391struct wpabuf * wps_ie_encapsulate(struct wpabuf *data) 392{ 393 struct wpabuf *ie; 394 const u8 *pos, *end; 395 396 ie = wpabuf_alloc(wpabuf_len(data) + 100); 397 if (ie == NULL) { 398 wpabuf_free(data); 399 return NULL; 400 } 401 402 pos = wpabuf_head(data); 403 end = pos + wpabuf_len(data); 404 405 while (end > pos) { 406 size_t frag_len = end - pos; 407 if (frag_len > 251) 408 frag_len = 251; 409 wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); 410 wpabuf_put_u8(ie, 4 + frag_len); 411 wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); 412 wpabuf_put_data(ie, pos, frag_len); 413 pos += frag_len; 414 } 415 416 wpabuf_free(data); 417 418 return ie; 419} 420