18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Wi-Fi Protected Setup - common functionality 304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Copyright (c) 2008-2012, 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" 12cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#include "common/defs.h" 13cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#include "common/ieee802_11_common.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/aes_wrap.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/dh_group5.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha256.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_i.h" 21cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#include "wps_dev_attr.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *label, u8 *res, size_t res_len) 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 i_buf[4], key_bits[4]; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[4]; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[4]; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, iter; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA256_MAC_LEN], *opos; 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE32(key_bits, res_len * 8); 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = i_buf; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = sizeof(i_buf); 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = label_prefix; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = label_prefix_len; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = (const u8 *) label; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[2] = os_strlen(label); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[3] = key_bits; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[3] = sizeof(key_bits); 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iter = (res_len + SHA256_MAC_LEN - 1) / SHA256_MAC_LEN; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt opos = res; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = res_len; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 1; i <= iter; i++) { 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE32(i_buf, i); 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256_vector(key, SHA256_MAC_LEN, 4, addr, len, hash); 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (i < iter) { 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(opos, hash, SHA256_MAC_LEN); 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt opos += SHA256_MAC_LEN; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= SHA256_MAC_LEN; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(opos, hash, left); 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_derive_keys(struct wps_data *wps) 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *pubkey, *dh_shared; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dhkey[SHA256_MAC_LEN], kdk[SHA256_MAC_LEN]; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[3]; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[3]; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 keys[WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN + WPS_EMSK_LEN]; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->dh_privkey == NULL) { 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Own DH private key not available"); 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pubkey = wps->registrar ? wps->dh_pubkey_e : wps->dh_pubkey_r; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pubkey == NULL) { 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Peer DH public key not available"); 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "WPS: DH peer Public Key", pubkey); 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dh_shared = dh5_derive_shared(wps->dh_ctx, pubkey, wps->dh_privkey); 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dh5_free(wps->dh_ctx); 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->dh_ctx = NULL; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dh_shared = wpabuf_zeropad(dh_shared, 192); 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dh_shared == NULL) { 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key"); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Own DH private key is not needed anymore */ 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(wps->dh_privkey); 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->dh_privkey = NULL; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH shared key", dh_shared); 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* DHKey = SHA-256(g^AB mod p) */ 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = wpabuf_head(dh_shared); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = wpabuf_len(dh_shared); 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(1, addr, len, dhkey); 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey)); 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(dh_shared); 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */ 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = wps->nonce_e; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = WPS_NONCE_LEN; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = wps->mac_addr_e; 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = ETH_ALEN; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = wps->nonce_r; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[2] = WPS_NONCE_LEN; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256_vector(dhkey, sizeof(dhkey), 3, addr, len, kdk); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: KDK", kdk, sizeof(kdk)); 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_kdf(kdk, NULL, 0, "Wi-Fi Easy and Secure Key Derivation", 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys, sizeof(keys)); 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wps->authkey, keys, WPS_AUTHKEY_LEN); 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wps->keywrapkey, keys + WPS_AUTHKEY_LEN, WPS_KEYWRAPKEY_LEN); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wps->emsk, keys + WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN, 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPS_EMSK_LEN); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: AuthKey", 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->authkey, WPS_AUTHKEY_LEN); 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: KeyWrapKey", 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->keywrapkey, WPS_KEYWRAPKEY_LEN); 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: EMSK", wps->emsk, WPS_EMSK_LEN); 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t dev_passwd_len) 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA256_MAC_LEN]; 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd, 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (dev_passwd_len + 1) / 2, hash); 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wps->psk1, hash, WPS_PSK_LEN); 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev_passwd + (dev_passwd_len + 1) / 2, 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev_passwd_len / 2, hash); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wps->psk2, hash, WPS_PSK_LEN); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password", 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev_passwd, dev_passwd_len); 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t encr_len) 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *decrypted; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t block_size = 16; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 pad; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* AES-128-CBC */ 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size) 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: No Encrypted Settings received"); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = wpabuf_alloc(encr_len - block_size); 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "WPS: Encrypted Settings", encr, encr_len); 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size); 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted), 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(decrypted))) { 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(decrypted); 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_MSGDUMP, "WPS: Decrypted Encrypted Settings", 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted); 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpabuf_head_u8(decrypted) + wpabuf_len(decrypted) - 1; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad = *pos; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pad > wpabuf_len(decrypted)) { 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value"); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(decrypted); 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < pad; i++) { 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos-- != pad) { 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad " 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "string"); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(decrypted); 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted->used -= pad; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return decrypted; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wps_pin_checksum - Compute PIN checksum 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pin: Seven digit PIN (i.e., eight digit PIN without the checksum digit) 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Checksum digit 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int wps_pin_checksum(unsigned int pin) 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int accum = 0; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pin) { 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt accum += 3 * (pin % 10); 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pin /= 10; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt accum += pin % 10; 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pin /= 10; 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return (10 - accum % 10) % 10; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wps_pin_valid - Check whether a PIN has a valid checksum 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pin: Eight digit PIN (i.e., including the checksum digit) 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 if checksum digit is valid, or 0 if not 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int wps_pin_valid(unsigned int pin) 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wps_pin_checksum(pin / 10) == (pin % 10); 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wps_generate_pin - Generate a random PIN 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Eight digit PIN (i.e., including the checksum digit) 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int wps_generate_pin(void) 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int val; 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Generate seven random digits for the PIN */ 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) { 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct os_time now; 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_get_time(&now); 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = os_random() ^ now.sec ^ now.usec; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val %= 10000000; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Append checksum digit */ 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return val * 10 + wps_pin_checksum(val); 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint wps_pin_str_valid(const char *pin) 25604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 25704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const char *p; 25804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt size_t len; 25904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 26004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt p = pin; 26104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt while (*p >= '0' && *p <= '9') 26204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt p++; 26304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (*p != '\0') 26404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 26504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 26604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt len = p - pin; 26704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return len == 4 || len == 8; 26804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 26904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 27004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_fail_event(struct wps_context *wps, enum wps_msg_type msg, 272b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt u16 config_error, u16 error_indication, const u8 *mac_addr) 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wps_event_data data; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.fail.msg = msg; 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.fail.config_error = config_error; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.fail.error_indication = error_indication; 283b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt os_memcpy(data.fail.peer_macaddr, mac_addr, ETH_ALEN); 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data); 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtvoid wps_success_event(struct wps_context *wps, const u8 *mac_addr) 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 290b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt union wps_event_data data; 291b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 295b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 296b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt os_memcpy(data.success.peer_macaddr, mac_addr, ETH_ALEN); 297b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, &data); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 301b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtvoid wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part, 302b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt const u8 *mac_addr) 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wps_event_data data; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.pwd_auth_fail.enrollee = enrollee; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.pwd_auth_fail.part = part; 312b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt os_memcpy(data.pwd_auth_fail.peer_macaddr, mac_addr, ETH_ALEN); 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, &data); 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_pbc_overlap_event(struct wps_context *wps) 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PBC_OVERLAP, NULL); 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_pbc_timeout_event(struct wps_context *wps) 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PBC_TIMEOUT, NULL); 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 335b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtvoid wps_pbc_active_event(struct wps_context *wps) 336b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 337b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (wps->event_cb == NULL) 338b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return; 339b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 340b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PBC_ACTIVE, NULL); 341b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 342b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 343b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 344b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtvoid wps_pbc_disable_event(struct wps_context *wps) 345b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 346b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (wps->event_cb == NULL) 347b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return; 348b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 349b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PBC_DISABLE, NULL); 350b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 351b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 352b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_OOB 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 355cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstruct wpabuf * wps_get_oob_cred(struct wps_context *wps, int rf_band, 356cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt int channel) 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_data data; 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *plain; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plain = wpabuf_alloc(500); 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (plain == NULL) { 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "credential"); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.wps = wps; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.auth_type = wps->auth_types; 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.encr_type = wps->encr_types; 372cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_build_cred(&data, plain) || 373cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt (rf_band && wps_build_rf_bands_attr(plain, rf_band)) || 374cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt (channel && wps_build_ap_channel(plain, channel)) || 375cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_mac_addr(plain, wps->dev.mac_addr) || 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_wfa_ext(plain, 0, NULL, 0)) { 3774b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_free(data.new_psk); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(plain); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3824b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt if (wps->wps_state == WPS_STATE_NOT_CONFIGURED && data.new_psk && 3834b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wps->ap) { 3844b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt struct wps_credential cred; 3854b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 3864b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based " 3874b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt "on credential token generation"); 3884b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 3894b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_memset(&cred, 0, sizeof(cred)); 3904b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_memcpy(cred.ssid, wps->ssid, wps->ssid_len); 3914b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt cred.ssid_len = wps->ssid_len; 3924b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK; 3934b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES; 3944b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_memcpy(cred.key, data.new_psk, data.new_psk_len); 3954b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt cred.key_len = data.new_psk_len; 3964b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 3974b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wps->wps_state = WPS_STATE_CONFIGURED; 3984b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wpa_hexdump_ascii_key(MSG_DEBUG, 3994b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt "WPS: Generated random passphrase", 4004b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt data.new_psk, data.new_psk_len); 4014b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt if (wps->cred_cb) 4024b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wps->cred_cb(wps->cb_ctx, &cred); 4034b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt } 4044b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 4054b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_free(data.new_psk); 4064b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return plain; 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 41104949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstruct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id, 41204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const struct wpabuf *pubkey, 41304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const struct wpabuf *dev_pw) 41404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 41504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf *data; 41604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 41704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data = wpabuf_alloc(200); 41804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (data == NULL) 41904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 42004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 421cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_build_oob_dev_pw(data, dev_pw_id, pubkey, 42204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_head(dev_pw), wpabuf_len(dev_pw)) || 42304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wps_build_wfa_ext(data, 0, NULL, 0)) { 42404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Failed to build NFC password " 42504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "token"); 42604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(data); 42704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 42804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 42904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 43004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return data; 43104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 43204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 43304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 43404949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint wps_oob_use_cred(struct wps_context *wps, struct wps_parse_attr *attr) 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf msg; 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = 0; i < attr->num_cred; i++) { 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_credential local_cred; 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_parse_attr cattr; 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&local_cred, 0, sizeof(local_cred)); 44404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_set(&msg, attr->cred[i], attr->cred_len[i]); 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_parse_msg(&msg, &cattr) < 0 || 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_process_cred(&cattr, &local_cred)) { 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB " 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "credential"); 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->cred_cb(wps->cb_ctx, &local_cred); 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_OOB */ 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]) 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *pos; 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* <categ>-<OUI>-<subcateg> */ 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(dev_type, atoi(str)); 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(str, '-'); 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hexstr2bin(pos, &dev_type[2], 4)) 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(pos, '-'); 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(&dev_type[6], atoi(pos)); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtchar * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf, 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len) 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf, buf_len, "%u-%08X-%u", 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(dev_type), WPA_GET_BE32(&dev_type[2]), 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(&dev_type[6])); 4926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(buf_len, ret)) 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid) 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[2]; 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[2]; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA1_MAC_LEN]; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 nsid[16] = { 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x52, 0x64, 0x80, 0xf8, 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0xc9, 0x9b, 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x4b, 0xe5, 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0xa6, 0x55, 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x58, 0xed, 0x5f, 0x5d, 0x60, 0x84 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = nsid; 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = sizeof(nsid); 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = mac_addr; 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = 6; 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha1_vector(2, addr, len, hash); 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(uuid, hash, 16); 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Version: 5 = named-based version using SHA-1 */ 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uuid[6] = (5 << 4) | (uuid[6] & 0x0f); 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Variant specified in RFC 4122 */ 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uuid[8] = 0x80 | (uuid[8] & 0x3f); 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu16 wps_config_methods_str2bin(const char *str) 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 methods = 0; 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (str == NULL) { 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Default to enabling methods based on build configuration */ 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_VIRT_DISPLAY; 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_NFC 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_NFC_INTERFACE; 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_NFC */ 538216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt#ifdef CONFIG_P2P 539216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt methods |= WPS_CONFIG_P2PS; 540216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt#endif /* CONFIG_P2P */ 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "ethernet")) 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_ETHERNET; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "label")) 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_LABEL; 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "display")) 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_DISPLAY; 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "ext_nfc_token")) 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_EXT_NFC_TOKEN; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "int_nfc_token")) 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_INT_NFC_TOKEN; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "nfc_interface")) 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_NFC_INTERFACE; 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "push_button")) 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_PUSHBUTTON; 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "keypad")) 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_KEYPAD; 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "virtual_display")) 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_VIRT_DISPLAY; 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "physical_display")) 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_PHY_DISPLAY; 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "virtual_push_button")) 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_VIRT_PUSHBUTTON; 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "physical_push_button")) 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_PHY_PUSHBUTTON; 566216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (os_strstr(str, "p2ps")) 567216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt methods |= WPS_CONFIG_P2PS; 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return methods; 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wps_build_wsc_ack(struct wps_data *wps) 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpabuf_alloc(1000); 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_build_version(msg) || 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_msg_type(msg, WPS_WSC_ACK) || 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_enrollee_nonce(wps, msg) || 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_registrar_nonce(wps, msg) || 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_wfa_ext(msg, 0, NULL, 0)) { 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wps_build_wsc_nack(struct wps_data *wps) 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpabuf_alloc(1000); 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_build_version(msg) || 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_msg_type(msg, WPS_WSC_NACK) || 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_enrollee_nonce(wps, msg) || 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_registrar_nonce(wps, msg) || 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_config_error(msg, wps->config_error) || 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_wfa_ext(msg, 0, NULL, 0)) { 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 61904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 62004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 62104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_WPS_NFC 622f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 623f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtstruct wpabuf * wps_nfc_token_build(int ndef, int id, struct wpabuf *pubkey, 624f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpabuf *dev_pw) 625f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{ 626f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpabuf *ret; 627f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 628f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (pubkey == NULL || dev_pw == NULL) 629f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return NULL; 630f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 631f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt ret = wps_build_nfc_pw_token(id, pubkey, dev_pw); 632f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (ndef && ret) { 633f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpabuf *tmp; 634f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt tmp = ndef_build_wifi(ret); 635f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpabuf_free(ret); 636f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (tmp == NULL) 637f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return NULL; 638f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt ret = tmp; 639f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 640f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 641f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return ret; 642f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt} 643f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 644f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 645cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtint wps_nfc_gen_dh(struct wpabuf **pubkey, struct wpabuf **privkey) 646cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 647cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *priv = NULL, *pub = NULL; 648cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt void *dh_ctx; 649cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 650cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt dh_ctx = dh5_init(&priv, &pub); 651cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (dh_ctx == NULL) 652cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return -1; 653cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt pub = wpabuf_zeropad(pub, 192); 654cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (pub == NULL) { 655cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_free(priv); 656cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return -1; 657cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 658cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "WPS: Generated new DH pubkey", pub); 659cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt dh5_free(dh_ctx); 660cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 661cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_free(*pubkey); 662cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt *pubkey = pub; 663cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_free(*privkey); 664cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt *privkey = priv; 665cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 666cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return 0; 667cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 668cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 669cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 67004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstruct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey, 67104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf **privkey, 67204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf **dev_pw) 67304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 674cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *pw; 67504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u16 val; 67604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 67704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pw = wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN); 67804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (pw == NULL) 67904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 68004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 68104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (random_get_bytes(wpabuf_put(pw, WPS_OOB_DEVICE_PASSWORD_LEN), 68204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt WPS_OOB_DEVICE_PASSWORD_LEN) || 68304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt random_get_bytes((u8 *) &val, sizeof(val))) { 68404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(pw); 68504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 68604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 68704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 688cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_nfc_gen_dh(pubkey, privkey) < 0) { 68904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(pw); 69004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 69104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 69204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 69304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *id = 0x10 + val % 0xfff0; 69404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(*dev_pw); 69504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *dev_pw = pw; 69604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 697f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return wps_nfc_token_build(ndef, *id, *pubkey, *dev_pw); 69804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 699f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 700cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 701cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstruct wpabuf * wps_build_nfc_handover_req(struct wps_context *ctx, 702cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *nfc_dh_pubkey) 703cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 704cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *msg; 705cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt void *len; 706cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 707cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (ctx == NULL) 708cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 709cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 710cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection " 711cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "handover request"); 712cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 713cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (nfc_dh_pubkey == NULL) { 714cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password " 715cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "configured"); 716cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 717cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 718cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 719cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt msg = wpabuf_alloc(1000); 720cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (msg == NULL) 721cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return msg; 722cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt len = wpabuf_put(msg, 2); 723cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 724cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER, 725cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt nfc_dh_pubkey, NULL, 0) || 726cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_uuid_e(msg, ctx->uuid) || 727cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_wfa_ext(msg, 0, NULL, 0)) { 728cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_free(msg); 729cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 730cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 731cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 732cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt WPA_PUT_BE16(len, wpabuf_len(msg) - 2); 733cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 734cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return msg; 735cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 736cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 737cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 738cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstatic int wps_build_ssid(struct wpabuf *msg, struct wps_context *wps) 739cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 740cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * SSID"); 741cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID in Connection Handover Select", 742cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps->ssid, wps->ssid_len); 743cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_put_be16(msg, ATTR_SSID); 744cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_put_be16(msg, wps->ssid_len); 745cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_put_data(msg, wps->ssid, wps->ssid_len); 746cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return 0; 747cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 748cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 749cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 750cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstatic int wps_build_ap_freq(struct wpabuf *msg, int freq) 751cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 752cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt enum hostapd_hw_mode mode; 753cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt u8 channel, rf_band; 754cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt u16 ap_channel; 755cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 756cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (freq <= 0) 757cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return 0; 758cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 759cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt mode = ieee80211_freq_to_chan(freq, &channel); 760cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (mode == NUM_HOSTAPD_MODES) 761cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return 0; /* Unknown channel */ 762cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 763cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (mode == HOSTAPD_MODE_IEEE80211G || mode == HOSTAPD_MODE_IEEE80211B) 764cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt rf_band = WPS_RF_24GHZ; 765cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt else if (mode == HOSTAPD_MODE_IEEE80211A) 766cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt rf_band = WPS_RF_50GHZ; 7671d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt else if (mode == HOSTAPD_MODE_IEEE80211AD) 7681d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt rf_band = WPS_RF_60GHZ; 769cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt else 770cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return 0; /* Unknown band */ 771cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt ap_channel = channel; 772cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 773cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_build_rf_bands_attr(msg, rf_band) || 774cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_ap_channel(msg, ap_channel)) 775cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return -1; 776cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 777cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return 0; 778cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 779cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 780cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 781cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstruct wpabuf * wps_build_nfc_handover_sel(struct wps_context *ctx, 782cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *nfc_dh_pubkey, 783cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt const u8 *bssid, int freq) 784cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 785cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *msg; 786cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt void *len; 787cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 788cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (ctx == NULL) 789cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 790cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 791cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection " 792cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "handover select"); 793cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 794cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (nfc_dh_pubkey == NULL) { 795cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password " 796cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "configured"); 797cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 798cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 799cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 800cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt msg = wpabuf_alloc(1000); 801cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (msg == NULL) 802cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return msg; 803cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt len = wpabuf_put(msg, 2); 804cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 805cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER, 806cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt nfc_dh_pubkey, NULL, 0) || 807cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_ssid(msg, ctx) || 808cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_ap_freq(msg, freq) || 809cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt (bssid && wps_build_mac_addr(msg, bssid)) || 810cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_wfa_ext(msg, 0, NULL, 0)) { 811cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_free(msg); 812cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 813cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 814cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 815cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt WPA_PUT_BE16(len, wpabuf_len(msg) - 2); 816cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 817cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return msg; 818cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 819cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 820cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 821cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstruct wpabuf * wps_build_nfc_handover_req_p2p(struct wps_context *ctx, 822cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *nfc_dh_pubkey) 823cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 824cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *msg; 825cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 826cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (ctx == NULL) 827cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 828cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 829cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection " 830cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "handover request (P2P)"); 831cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 832cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (nfc_dh_pubkey == NULL) { 833cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: No NFC DH Public Key configured"); 834cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 835cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 836cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 837cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt msg = wpabuf_alloc(1000); 838cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (msg == NULL) 839cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return msg; 840cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 841cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_build_manufacturer(&ctx->dev, msg) || 842cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_model_name(&ctx->dev, msg) || 843cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_model_number(&ctx->dev, msg) || 844cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER, 845cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt nfc_dh_pubkey, NULL, 0) || 846cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_rf_bands(&ctx->dev, msg, 0) || 847cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_serial_number(&ctx->dev, msg) || 848cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_uuid_e(msg, ctx->uuid) || 849cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_wfa_ext(msg, 0, NULL, 0)) { 850cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_free(msg); 851cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 852cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 853cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 854cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return msg; 855cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 856cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 857cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 858cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstruct wpabuf * wps_build_nfc_handover_sel_p2p(struct wps_context *ctx, 859cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt int nfc_dev_pw_id, 860cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *nfc_dh_pubkey, 861cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *nfc_dev_pw) 862cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 863cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *msg; 864cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt const u8 *dev_pw; 865cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt size_t dev_pw_len; 866cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 867cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (ctx == NULL) 868cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 869cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 870cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection " 871cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "handover select (P2P)"); 872cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 873cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (nfc_dh_pubkey == NULL || 874cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt (nfc_dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER && 875cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt nfc_dev_pw == NULL)) { 876cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password " 877cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "configured"); 878cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 879cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 880cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 881cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt msg = wpabuf_alloc(1000); 882cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (msg == NULL) 883cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return msg; 884cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 885cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (nfc_dev_pw) { 886cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt dev_pw = wpabuf_head(nfc_dev_pw); 887cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt dev_pw_len = wpabuf_len(nfc_dev_pw); 888cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } else { 889cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt dev_pw = NULL; 890cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt dev_pw_len = 0; 891cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 892cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 893cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_build_manufacturer(&ctx->dev, msg) || 894cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_model_name(&ctx->dev, msg) || 895cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_model_number(&ctx->dev, msg) || 896cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_oob_dev_pw(msg, nfc_dev_pw_id, nfc_dh_pubkey, 897cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt dev_pw, dev_pw_len) || 898cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_rf_bands(&ctx->dev, msg, 0) || 899cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_serial_number(&ctx->dev, msg) || 900cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_uuid_e(msg, ctx->uuid) || 901cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_wfa_ext(msg, 0, NULL, 0)) { 902cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_free(msg); 903cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 904cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 905cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 906cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return msg; 907cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 908cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 90904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_WPS_NFC */ 910