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 */ 93849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt wpabuf_clear_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)); 103849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt wpabuf_clear_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 132849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidtint wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, 133849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt size_t dev_passwd_len) 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA256_MAC_LEN]; 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 137849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd, 138849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt (dev_passwd_len + 1) / 2, hash) < 0) 139849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt return -1; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wps->psk1, hash, WPS_PSK_LEN); 141849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, 142849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt dev_passwd + (dev_passwd_len + 1) / 2, 143849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt dev_passwd_len / 2, hash) < 0) 144849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt return -1; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wps->psk2, hash, WPS_PSK_LEN); 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password", 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev_passwd, dev_passwd_len); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN); 151849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt return 0; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t encr_len) 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *decrypted; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t block_size = 16; 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 pad; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* AES-128-CBC */ 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size) 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: No Encrypted Settings received"); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = wpabuf_alloc(encr_len - block_size); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "WPS: Encrypted Settings", encr, encr_len); 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size); 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted), 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(decrypted))) { 179849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt wpabuf_clear_free(decrypted); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_MSGDUMP, "WPS: Decrypted Encrypted Settings", 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpabuf_head_u8(decrypted) + wpabuf_len(decrypted) - 1; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad = *pos; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pad > wpabuf_len(decrypted)) { 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value"); 190849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt wpabuf_clear_free(decrypted); 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < pad; i++) { 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos-- != pad) { 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad " 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "string"); 197849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt wpabuf_clear_free(decrypted); 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted->used -= pad; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return decrypted; 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wps_pin_checksum - Compute PIN checksum 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pin: Seven digit PIN (i.e., eight digit PIN without the checksum digit) 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Checksum digit 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int wps_pin_checksum(unsigned int pin) 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int accum = 0; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pin) { 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt accum += 3 * (pin % 10); 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pin /= 10; 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt accum += pin % 10; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pin /= 10; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return (10 - accum % 10) % 10; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wps_pin_valid - Check whether a PIN has a valid checksum 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pin: Eight digit PIN (i.e., including the checksum digit) 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 if checksum digit is valid, or 0 if not 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int wps_pin_valid(unsigned int pin) 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wps_pin_checksum(pin / 10) == (pin % 10); 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wps_generate_pin - Generate a random PIN 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Eight digit PIN (i.e., including the checksum digit) 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 24157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidtint wps_generate_pin(unsigned int *pin) 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int val; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Generate seven random digits for the PIN */ 24657c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) 24757c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt return -1; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val %= 10000000; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Append checksum digit */ 25157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt *pin = val * 10 + wps_pin_checksum(val); 25257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt return 0; 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint wps_pin_str_valid(const char *pin) 25704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 25804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const char *p; 25904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt size_t len; 26004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 26104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt p = pin; 26204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt while (*p >= '0' && *p <= '9') 26304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt p++; 26404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (*p != '\0') 26504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 26604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 26704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt len = p - pin; 26804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return len == 4 || len == 8; 26904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 27004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 27104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_fail_event(struct wps_context *wps, enum wps_msg_type msg, 273b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt u16 config_error, u16 error_indication, const u8 *mac_addr) 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wps_event_data data; 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.fail.msg = msg; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.fail.config_error = config_error; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.fail.error_indication = error_indication; 284b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt os_memcpy(data.fail.peer_macaddr, mac_addr, ETH_ALEN); 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data); 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 289b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtvoid wps_success_event(struct wps_context *wps, const u8 *mac_addr) 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 291b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt union wps_event_data data; 292b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 296b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 297b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt os_memcpy(data.success.peer_macaddr, mac_addr, ETH_ALEN); 298b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, &data); 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 302b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtvoid wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part, 303b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt const u8 *mac_addr) 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wps_event_data data; 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.pwd_auth_fail.enrollee = enrollee; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.pwd_auth_fail.part = part; 313b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt os_memcpy(data.pwd_auth_fail.peer_macaddr, mac_addr, ETH_ALEN); 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, &data); 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_pbc_overlap_event(struct wps_context *wps) 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PBC_OVERLAP, NULL); 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_pbc_timeout_event(struct wps_context *wps) 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PBC_TIMEOUT, NULL); 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 336b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtvoid wps_pbc_active_event(struct wps_context *wps) 337b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 338b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (wps->event_cb == NULL) 339b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return; 340b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 341b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PBC_ACTIVE, NULL); 342b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 343b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 344b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 345b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtvoid wps_pbc_disable_event(struct wps_context *wps) 346b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 347b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (wps->event_cb == NULL) 348b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return; 349b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 350b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PBC_DISABLE, NULL); 351b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 352b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 353b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_OOB 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 356cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstruct wpabuf * wps_get_oob_cred(struct wps_context *wps, int rf_band, 357cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt int channel) 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_data data; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *plain; 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plain = wpabuf_alloc(500); 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (plain == NULL) { 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "credential"); 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.wps = wps; 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.auth_type = wps->auth_types; 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.encr_type = wps->encr_types; 373cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_build_cred(&data, plain) || 374cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt (rf_band && wps_build_rf_bands_attr(plain, rf_band)) || 375cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt (channel && wps_build_ap_channel(plain, channel)) || 376cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_mac_addr(plain, wps->dev.mac_addr) || 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_wfa_ext(plain, 0, NULL, 0)) { 3784b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_free(data.new_psk); 379849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt wpabuf_clear_free(plain); 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3834b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt if (wps->wps_state == WPS_STATE_NOT_CONFIGURED && data.new_psk && 3844b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wps->ap) { 3854b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt struct wps_credential cred; 3864b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 3874b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based " 3884b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt "on credential token generation"); 3894b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 3904b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_memset(&cred, 0, sizeof(cred)); 3914b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_memcpy(cred.ssid, wps->ssid, wps->ssid_len); 3924b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt cred.ssid_len = wps->ssid_len; 3934b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK; 3944b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES; 3954b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_memcpy(cred.key, data.new_psk, data.new_psk_len); 3964b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt cred.key_len = data.new_psk_len; 3974b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 3984b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wps->wps_state = WPS_STATE_CONFIGURED; 3994b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wpa_hexdump_ascii_key(MSG_DEBUG, 4004b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt "WPS: Generated random passphrase", 4014b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt data.new_psk, data.new_psk_len); 4024b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt if (wps->cred_cb) 4034b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wps->cred_cb(wps->cb_ctx, &cred); 4044b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt } 4054b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 4064b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_free(data.new_psk); 4074b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return plain; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 41204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstruct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id, 41304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const struct wpabuf *pubkey, 41404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const struct wpabuf *dev_pw) 41504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 41604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf *data; 41704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 41804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data = wpabuf_alloc(200); 41904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (data == NULL) 42004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 42104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 422cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_build_oob_dev_pw(data, dev_pw_id, pubkey, 42304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_head(dev_pw), wpabuf_len(dev_pw)) || 42404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wps_build_wfa_ext(data, 0, NULL, 0)) { 42504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Failed to build NFC password " 42604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "token"); 427849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt wpabuf_clear_free(data); 42804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 42904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 43004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 43104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return data; 43204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 43304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 43404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 43504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint wps_oob_use_cred(struct wps_context *wps, struct wps_parse_attr *attr) 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf msg; 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = 0; i < attr->num_cred; i++) { 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_credential local_cred; 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_parse_attr cattr; 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&local_cred, 0, sizeof(local_cred)); 44504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_set(&msg, attr->cred[i], attr->cred_len[i]); 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_parse_msg(&msg, &cattr) < 0 || 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_process_cred(&cattr, &local_cred)) { 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB " 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "credential"); 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->cred_cb(wps->cb_ctx, &local_cred); 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_OOB */ 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]) 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *pos; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* <categ>-<OUI>-<subcateg> */ 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(dev_type, atoi(str)); 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(str, '-'); 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hexstr2bin(pos, &dev_type[2], 4)) 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(pos, '-'); 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(&dev_type[6], atoi(pos)); 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtchar * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf, 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len) 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf, buf_len, "%u-%08X-%u", 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(dev_type), WPA_GET_BE32(&dev_type[2]), 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(&dev_type[6])); 4936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(buf_len, ret)) 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid) 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[2]; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[2]; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA1_MAC_LEN]; 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 nsid[16] = { 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x52, 0x64, 0x80, 0xf8, 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0xc9, 0x9b, 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x4b, 0xe5, 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0xa6, 0x55, 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x58, 0xed, 0x5f, 0x5d, 0x60, 0x84 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = nsid; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = sizeof(nsid); 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = mac_addr; 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = 6; 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha1_vector(2, addr, len, hash); 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(uuid, hash, 16); 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Version: 5 = named-based version using SHA-1 */ 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uuid[6] = (5 << 4) | (uuid[6] & 0x0f); 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Variant specified in RFC 4122 */ 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uuid[8] = 0x80 | (uuid[8] & 0x3f); 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu16 wps_config_methods_str2bin(const char *str) 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 methods = 0; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 532d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (str == NULL || str[0] == '\0') { 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Default to enabling methods based on build configuration */ 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_VIRT_DISPLAY; 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_NFC 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_NFC_INTERFACE; 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_NFC */ 539216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt#ifdef CONFIG_P2P 540216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt methods |= WPS_CONFIG_P2PS; 541216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt#endif /* CONFIG_P2P */ 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "ethernet")) 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_ETHERNET; 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "label")) 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_LABEL; 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "display")) 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_DISPLAY; 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "ext_nfc_token")) 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_EXT_NFC_TOKEN; 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "int_nfc_token")) 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_INT_NFC_TOKEN; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "nfc_interface")) 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_NFC_INTERFACE; 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "push_button")) 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_PUSHBUTTON; 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "keypad")) 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_KEYPAD; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "virtual_display")) 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_VIRT_DISPLAY; 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "physical_display")) 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_PHY_DISPLAY; 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "virtual_push_button")) 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_VIRT_PUSHBUTTON; 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "physical_push_button")) 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_PHY_PUSHBUTTON; 567216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt if (os_strstr(str, "p2ps")) 568216983bceec7c450951e2fbcd076b5c75d432e57Dmitry Shmidt methods |= WPS_CONFIG_P2PS; 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return methods; 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wps_build_wsc_ack(struct wps_data *wps) 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpabuf_alloc(1000); 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_build_version(msg) || 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_msg_type(msg, WPS_WSC_ACK) || 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_enrollee_nonce(wps, msg) || 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_registrar_nonce(wps, msg) || 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_wfa_ext(msg, 0, NULL, 0)) { 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wps_build_wsc_nack(struct wps_data *wps) 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpabuf_alloc(1000); 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_build_version(msg) || 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_msg_type(msg, WPS_WSC_NACK) || 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_enrollee_nonce(wps, msg) || 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_registrar_nonce(wps, msg) || 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_config_error(msg, wps->config_error) || 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_wfa_ext(msg, 0, NULL, 0)) { 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 62004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 62104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 62204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_WPS_NFC 623f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 624f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtstruct wpabuf * wps_nfc_token_build(int ndef, int id, struct wpabuf *pubkey, 625f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpabuf *dev_pw) 626f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{ 627f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpabuf *ret; 628f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 629f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (pubkey == NULL || dev_pw == NULL) 630f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return NULL; 631f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 632f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt ret = wps_build_nfc_pw_token(id, pubkey, dev_pw); 633f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (ndef && ret) { 634f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpabuf *tmp; 635f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt tmp = ndef_build_wifi(ret); 636f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpabuf_free(ret); 637f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (tmp == NULL) 638f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return NULL; 639f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt ret = tmp; 640f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 641f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 642f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return ret; 643f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt} 644f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 645f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 646cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtint wps_nfc_gen_dh(struct wpabuf **pubkey, struct wpabuf **privkey) 647cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 648cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *priv = NULL, *pub = NULL; 649cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt void *dh_ctx; 650cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 651cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt dh_ctx = dh5_init(&priv, &pub); 652cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (dh_ctx == NULL) 653cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return -1; 654cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt pub = wpabuf_zeropad(pub, 192); 655cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (pub == NULL) { 656cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_free(priv); 657cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return -1; 658cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 659cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "WPS: Generated new DH pubkey", pub); 660cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt dh5_free(dh_ctx); 661cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 662cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_free(*pubkey); 663cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt *pubkey = pub; 664849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt wpabuf_clear_free(*privkey); 665cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt *privkey = priv; 666cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 667cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return 0; 668cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 669cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 670cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 67104949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstruct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey, 67204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf **privkey, 67304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf **dev_pw) 67404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 675cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *pw; 67604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u16 val; 67704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 67804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pw = wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN); 67904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (pw == NULL) 68004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 68104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 68204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (random_get_bytes(wpabuf_put(pw, WPS_OOB_DEVICE_PASSWORD_LEN), 68304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt WPS_OOB_DEVICE_PASSWORD_LEN) || 68404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt random_get_bytes((u8 *) &val, sizeof(val))) { 68504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(pw); 68604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 68704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 68804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 689cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_nfc_gen_dh(pubkey, privkey) < 0) { 69004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(pw); 69104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 69204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 69304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 69404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *id = 0x10 + val % 0xfff0; 695849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt wpabuf_clear_free(*dev_pw); 69604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *dev_pw = pw; 69704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 698f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return wps_nfc_token_build(ndef, *id, *pubkey, *dev_pw); 69904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 700f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 701cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 702cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstruct wpabuf * wps_build_nfc_handover_req(struct wps_context *ctx, 703cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *nfc_dh_pubkey) 704cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 705cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *msg; 706cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt void *len; 707cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 708cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (ctx == NULL) 709cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 710cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 711cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection " 712cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "handover request"); 713cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 714cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (nfc_dh_pubkey == NULL) { 715cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password " 716cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "configured"); 717cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 718cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 719cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 720cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt msg = wpabuf_alloc(1000); 721cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (msg == NULL) 722cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return msg; 723cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt len = wpabuf_put(msg, 2); 724cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 725cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER, 726cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt nfc_dh_pubkey, NULL, 0) || 727cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_uuid_e(msg, ctx->uuid) || 728cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_wfa_ext(msg, 0, NULL, 0)) { 729cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_free(msg); 730cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 731cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 732cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 733cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt WPA_PUT_BE16(len, wpabuf_len(msg) - 2); 734cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 735cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return msg; 736cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 737cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 738cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 739cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstatic int wps_build_ssid(struct wpabuf *msg, struct wps_context *wps) 740cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 741cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: * SSID"); 742cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID in Connection Handover Select", 743cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps->ssid, wps->ssid_len); 744cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_put_be16(msg, ATTR_SSID); 745cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_put_be16(msg, wps->ssid_len); 746cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_put_data(msg, wps->ssid, wps->ssid_len); 747cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return 0; 748cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 749cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 750cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 751cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstatic int wps_build_ap_freq(struct wpabuf *msg, int freq) 752cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 753cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt enum hostapd_hw_mode mode; 754cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt u8 channel, rf_band; 755cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt u16 ap_channel; 756cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 757cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (freq <= 0) 758cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return 0; 759cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 760cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt mode = ieee80211_freq_to_chan(freq, &channel); 761cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (mode == NUM_HOSTAPD_MODES) 762cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return 0; /* Unknown channel */ 763cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 764cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (mode == HOSTAPD_MODE_IEEE80211G || mode == HOSTAPD_MODE_IEEE80211B) 765cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt rf_band = WPS_RF_24GHZ; 766cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt else if (mode == HOSTAPD_MODE_IEEE80211A) 767cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt rf_band = WPS_RF_50GHZ; 7681d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt else if (mode == HOSTAPD_MODE_IEEE80211AD) 7691d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt rf_band = WPS_RF_60GHZ; 770cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt else 771cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return 0; /* Unknown band */ 772cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt ap_channel = channel; 773cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 774cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_build_rf_bands_attr(msg, rf_band) || 775cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_ap_channel(msg, ap_channel)) 776cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return -1; 777cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 778cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return 0; 779cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 780cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 781cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 782cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstruct wpabuf * wps_build_nfc_handover_sel(struct wps_context *ctx, 783cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *nfc_dh_pubkey, 784cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt const u8 *bssid, int freq) 785cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 786cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *msg; 787cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt void *len; 788cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 789cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (ctx == NULL) 790cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 791cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 792cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection " 793cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "handover select"); 794cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 795cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (nfc_dh_pubkey == NULL) { 796cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password " 797cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "configured"); 798cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 799cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 800cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 801cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt msg = wpabuf_alloc(1000); 802cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (msg == NULL) 803cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return msg; 804cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt len = wpabuf_put(msg, 2); 805cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 806cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER, 807cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt nfc_dh_pubkey, NULL, 0) || 808cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_ssid(msg, ctx) || 809cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_ap_freq(msg, freq) || 810cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt (bssid && wps_build_mac_addr(msg, bssid)) || 811cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_wfa_ext(msg, 0, NULL, 0)) { 812cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_free(msg); 813cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 814cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 815cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 816cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt WPA_PUT_BE16(len, wpabuf_len(msg) - 2); 817cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 818cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return msg; 819cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 820cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 821cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 822cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstruct wpabuf * wps_build_nfc_handover_req_p2p(struct wps_context *ctx, 823cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *nfc_dh_pubkey) 824cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 825cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *msg; 826cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 827cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (ctx == NULL) 828cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 829cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 830cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection " 831cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "handover request (P2P)"); 832cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 833cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (nfc_dh_pubkey == NULL) { 834cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: No NFC DH Public Key configured"); 835cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 836cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 837cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 838cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt msg = wpabuf_alloc(1000); 839cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (msg == NULL) 840cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return msg; 841cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 842cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_build_manufacturer(&ctx->dev, msg) || 843cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_model_name(&ctx->dev, msg) || 844cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_model_number(&ctx->dev, msg) || 845cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER, 846cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt nfc_dh_pubkey, NULL, 0) || 847cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_rf_bands(&ctx->dev, msg, 0) || 848cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_serial_number(&ctx->dev, msg) || 849cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_uuid_e(msg, ctx->uuid) || 850cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_wfa_ext(msg, 0, NULL, 0)) { 851cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_free(msg); 852cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 853cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 854cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 855cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return msg; 856cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 857cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 858cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 859cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstruct wpabuf * wps_build_nfc_handover_sel_p2p(struct wps_context *ctx, 860cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt int nfc_dev_pw_id, 861cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *nfc_dh_pubkey, 862cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *nfc_dev_pw) 863cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 864cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt struct wpabuf *msg; 865cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt const u8 *dev_pw; 866cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt size_t dev_pw_len; 867cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 868cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (ctx == NULL) 869cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 870cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 871cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection " 872cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "handover select (P2P)"); 873cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 874cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (nfc_dh_pubkey == NULL || 875cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt (nfc_dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER && 876cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt nfc_dev_pw == NULL)) { 877cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password " 878cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt "configured"); 879cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 880cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 881cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 882cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt msg = wpabuf_alloc(1000); 883cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (msg == NULL) 884cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return msg; 885cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 886cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (nfc_dev_pw) { 887cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt dev_pw = wpabuf_head(nfc_dev_pw); 888cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt dev_pw_len = wpabuf_len(nfc_dev_pw); 889cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } else { 890cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt dev_pw = NULL; 891cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt dev_pw_len = 0; 892cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 893cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 894cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt if (wps_build_manufacturer(&ctx->dev, msg) || 895cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_model_name(&ctx->dev, msg) || 896cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_model_number(&ctx->dev, msg) || 897cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_oob_dev_pw(msg, nfc_dev_pw_id, nfc_dh_pubkey, 898cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt dev_pw, dev_pw_len) || 899cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_rf_bands(&ctx->dev, msg, 0) || 900cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_serial_number(&ctx->dev, msg) || 901cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_uuid_e(msg, ctx->uuid) || 902cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wps_build_wfa_ext(msg, 0, NULL, 0)) { 903cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt wpabuf_free(msg); 904cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return NULL; 905cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 906cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 907cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt return msg; 908cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt} 909cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 91004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_WPS_NFC */ 911