wps_common.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Wi-Fi Protected Setup - common functionality 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation. 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license. 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/aes_wrap.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/dh_group5.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha256.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_i.h" 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_dev_attr.h" 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *label, u8 *res, size_t res_len) 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 i_buf[4], key_bits[4]; 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[4]; 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[4]; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, iter; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA256_MAC_LEN], *opos; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE32(key_bits, res_len * 8); 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = i_buf; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = sizeof(i_buf); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = label_prefix; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = label_prefix_len; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = (const u8 *) label; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[2] = os_strlen(label); 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[3] = key_bits; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[3] = sizeof(key_bits); 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iter = (res_len + SHA256_MAC_LEN - 1) / SHA256_MAC_LEN; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt opos = res; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = res_len; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 1; i <= iter; i++) { 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE32(i_buf, i); 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256_vector(key, SHA256_MAC_LEN, 4, addr, len, hash); 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (i < iter) { 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(opos, hash, SHA256_MAC_LEN); 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt opos += SHA256_MAC_LEN; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= SHA256_MAC_LEN; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(opos, hash, left); 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_derive_keys(struct wps_data *wps) 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *pubkey, *dh_shared; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dhkey[SHA256_MAC_LEN], kdk[SHA256_MAC_LEN]; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[3]; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[3]; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 keys[WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN + WPS_EMSK_LEN]; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->dh_privkey == NULL) { 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Own DH private key not available"); 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pubkey = wps->registrar ? wps->dh_pubkey_e : wps->dh_pubkey_r; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pubkey == NULL) { 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Peer DH public key not available"); 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "WPS: DH peer Public Key", pubkey); 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dh_shared = dh5_derive_shared(wps->dh_ctx, pubkey, wps->dh_privkey); 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dh5_free(wps->dh_ctx); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->dh_ctx = NULL; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dh_shared = wpabuf_zeropad(dh_shared, 192); 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dh_shared == NULL) { 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key"); 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Own DH private key is not needed anymore */ 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(wps->dh_privkey); 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->dh_privkey = NULL; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH shared key", dh_shared); 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* DHKey = SHA-256(g^AB mod p) */ 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = wpabuf_head(dh_shared); 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = wpabuf_len(dh_shared); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(1, addr, len, dhkey); 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey)); 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(dh_shared); 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */ 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = wps->nonce_e; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = WPS_NONCE_LEN; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = wps->mac_addr_e; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = ETH_ALEN; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = wps->nonce_r; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[2] = WPS_NONCE_LEN; 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256_vector(dhkey, sizeof(dhkey), 3, addr, len, kdk); 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: KDK", kdk, sizeof(kdk)); 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_kdf(kdk, NULL, 0, "Wi-Fi Easy and Secure Key Derivation", 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys, sizeof(keys)); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wps->authkey, keys, WPS_AUTHKEY_LEN); 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wps->keywrapkey, keys + WPS_AUTHKEY_LEN, WPS_KEYWRAPKEY_LEN); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wps->emsk, keys + WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN, 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPS_EMSK_LEN); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: AuthKey", 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->authkey, WPS_AUTHKEY_LEN); 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: KeyWrapKey", 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->keywrapkey, WPS_KEYWRAPKEY_LEN); 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: EMSK", wps->emsk, WPS_EMSK_LEN); 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t dev_passwd_len) 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA256_MAC_LEN]; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd, 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (dev_passwd_len + 1) / 2, hash); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wps->psk1, hash, WPS_PSK_LEN); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev_passwd + (dev_passwd_len + 1) / 2, 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev_passwd_len / 2, hash); 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wps->psk2, hash, WPS_PSK_LEN); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password", 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev_passwd, dev_passwd_len); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN); 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t encr_len) 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *decrypted; 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t block_size = 16; 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 pad; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* AES-128-CBC */ 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size) 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: No Encrypted Settings received"); 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = wpabuf_alloc(encr_len - block_size); 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "WPS: Encrypted Settings", encr, encr_len); 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted), 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(decrypted))) { 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(decrypted); 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_MSGDUMP, "WPS: Decrypted Encrypted Settings", 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted); 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpabuf_head_u8(decrypted) + wpabuf_len(decrypted) - 1; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad = *pos; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pad > wpabuf_len(decrypted)) { 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value"); 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(decrypted); 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < pad; i++) { 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos-- != pad) { 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad " 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "string"); 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(decrypted); 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted->used -= pad; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return decrypted; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wps_pin_checksum - Compute PIN checksum 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pin: Seven digit PIN (i.e., eight digit PIN without the checksum digit) 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Checksum digit 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int wps_pin_checksum(unsigned int pin) 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int accum = 0; 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pin) { 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt accum += 3 * (pin % 10); 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pin /= 10; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt accum += pin % 10; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pin /= 10; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return (10 - accum % 10) % 10; 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wps_pin_valid - Check whether a PIN has a valid checksum 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pin: Eight digit PIN (i.e., including the checksum digit) 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 if checksum digit is valid, or 0 if not 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int wps_pin_valid(unsigned int pin) 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wps_pin_checksum(pin / 10) == (pin % 10); 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wps_generate_pin - Generate a random PIN 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Eight digit PIN (i.e., including the checksum digit) 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int wps_generate_pin(void) 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int val; 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Generate seven random digits for the PIN */ 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) { 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct os_time now; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_get_time(&now); 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = os_random() ^ now.sec ^ now.usec; 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val %= 10000000; 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Append checksum digit */ 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return val * 10 + wps_pin_checksum(val); 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_fail_event(struct wps_context *wps, enum wps_msg_type msg, 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 config_error, u16 error_indication) 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wps_event_data data; 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.fail.msg = msg; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.fail.config_error = config_error; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.fail.error_indication = error_indication; 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_success_event(struct wps_context *wps) 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, NULL); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part) 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wps_event_data data; 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.pwd_auth_fail.enrollee = enrollee; 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.pwd_auth_fail.part = part; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, &data); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_pbc_overlap_event(struct wps_context *wps) 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PBC_OVERLAP, NULL); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_pbc_timeout_event(struct wps_context *wps) 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PBC_TIMEOUT, NULL); 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_OOB 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * wps_get_oob_cred(struct wps_context *wps) 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_data data; 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *plain; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plain = wpabuf_alloc(500); 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (plain == NULL) { 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "credential"); 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.wps = wps; 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.auth_type = wps->auth_types; 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.encr_type = wps->encr_types; 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_build_version(plain) || 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_cred(&data, plain) || 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_wfa_ext(plain, 0, NULL, 0)) { 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(plain); 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return plain; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * wps_get_oob_dev_pwd(struct wps_context *wps) 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *data; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = wpabuf_alloc(9 + WPS_OOB_DEVICE_PASSWORD_ATTR_LEN); 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) { 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "device password attribute"); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(wps->oob_conf.dev_password); 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->oob_conf.dev_password = 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1); 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->oob_conf.dev_password == NULL) { 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "device password"); 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data); 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_build_version(data) || 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_oob_dev_password(data, wps) || 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_wfa_ext(data, 0, NULL, 0)) { 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Build OOB device password " 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "attribute error"); 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data); 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_parse_oob_dev_pwd(struct wps_context *wps, 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *data) 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct oob_conf_data *oob_conf = &wps->oob_conf; 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_parse_attr attr; 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_parse_msg(data, &attr) < 0 || 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr.oob_dev_password == NULL) { 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPS: OOB device password not found"); 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = attr.oob_dev_password; 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oob_conf->pubkey_hash = 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_alloc_copy(pos, WPS_OOB_PUBKEY_HASH_LEN); 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (oob_conf->pubkey_hash == NULL) { 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "public key hash"); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += WPS_OOB_PUBKEY_HASH_LEN; 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->oob_dev_pw_id = WPA_GET_BE16(pos); 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += sizeof(wps->oob_dev_pw_id); 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oob_conf->dev_password = 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1); 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (oob_conf->dev_password == NULL) { 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "device password"); 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_snprintf_hex_uppercase(wpabuf_put(oob_conf->dev_password, 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_size(oob_conf->dev_password)), 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_size(oob_conf->dev_password), pos, 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPS_OOB_DEVICE_PASSWORD_LEN); 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_parse_oob_cred(struct wps_context *wps, struct wpabuf *data) 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf msg; 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_parse_attr attr; 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_parse_msg(data, &attr) < 0 || attr.num_cred <= 0) { 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPS: OOB credential not found"); 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < attr.num_cred; i++) { 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_credential local_cred; 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_parse_attr cattr; 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&local_cred, 0, sizeof(local_cred)); 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&msg, attr.cred[i], attr.cred_len[i]); 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_parse_msg(&msg, &cattr) < 0 || 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_process_cred(&cattr, &local_cred)) { 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB " 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "credential"); 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->cred_cb(wps->cb_ctx, &local_cred); 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_process_oob(struct wps_context *wps, struct oob_device_data *oob_dev, 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int registrar) 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *data; 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret, write_f, oob_method = wps->oob_conf.oob_method; 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *oob_priv; 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt write_f = oob_method == OOB_METHOD_DEV_PWD_E ? !registrar : registrar; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oob_priv = oob_dev->init_func(wps, oob_dev, registrar); 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (oob_priv == NULL) { 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Failed to initialize OOB device"); 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (write_f) { 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (oob_method == OOB_METHOD_CRED) 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = wps_get_oob_cred(wps); 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = wps_get_oob_dev_pwd(wps); 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL || oob_dev->write_func(oob_priv, data) < 0) 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = oob_dev->read_func(oob_priv); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (oob_method == OOB_METHOD_CRED) 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = wps_parse_oob_cred(wps, data); 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = wps_parse_oob_dev_pwd(wps, data); 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data); 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oob_dev->deinit_func(oob_priv); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Failed to process OOB data"); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct oob_device_data * wps_get_oob_device(char *device_type) 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_UFD 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(device_type, "ufd") != NULL) 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return &oob_ufd_device_data; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_UFD */ 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_NFC 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(device_type, "nfc") != NULL) 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return &oob_nfc_device_data; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_NFC */ 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_NFC 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct oob_nfc_device_data * wps_get_oob_nfc_device(char *device_name) 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (device_name == NULL) 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_NFC_PN531 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(device_name, "pn531") != NULL) 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return &oob_nfc_pn531_device_data; 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_NFC_PN531 */ 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_NFC */ 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_get_oob_method(char *method) 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(method, "pin-e") != NULL) 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return OOB_METHOD_DEV_PWD_E; 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(method, "pin-r") != NULL) 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return OOB_METHOD_DEV_PWD_R; 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(method, "cred") != NULL) 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return OOB_METHOD_CRED; 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return OOB_METHOD_UNKNOWN; 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_OOB */ 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]) 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *pos; 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* <categ>-<OUI>-<subcateg> */ 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(dev_type, atoi(str)); 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(str, '-'); 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hexstr2bin(pos, &dev_type[2], 4)) 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(pos, '-'); 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(&dev_type[6], atoi(pos)); 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtchar * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf, 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len) 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf, buf_len, "%u-%08X-%u", 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(dev_type), WPA_GET_BE32(&dev_type[2]), 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(&dev_type[6])); 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (unsigned int) ret >= buf_len) 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid) 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[2]; 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[2]; 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA1_MAC_LEN]; 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 nsid[16] = { 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x52, 0x64, 0x80, 0xf8, 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0xc9, 0x9b, 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x4b, 0xe5, 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0xa6, 0x55, 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x58, 0xed, 0x5f, 0x5d, 0x60, 0x84 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = nsid; 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = sizeof(nsid); 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = mac_addr; 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = 6; 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha1_vector(2, addr, len, hash); 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(uuid, hash, 16); 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Version: 5 = named-based version using SHA-1 */ 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uuid[6] = (5 << 4) | (uuid[6] & 0x0f); 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Variant specified in RFC 4122 */ 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uuid[8] = 0x80 | (uuid[8] & 0x3f); 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu16 wps_config_methods_str2bin(const char *str) 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 methods = 0; 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (str == NULL) { 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Default to enabling methods based on build configuration */ 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS2 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_VIRT_DISPLAY; 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS2 */ 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_UFD 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_USBA; 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_UFD */ 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_NFC 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_NFC_INTERFACE; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_NFC */ 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "usba")) 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_USBA; 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "ethernet")) 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_ETHERNET; 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "label")) 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_LABEL; 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "display")) 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_DISPLAY; 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "ext_nfc_token")) 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_EXT_NFC_TOKEN; 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "int_nfc_token")) 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_INT_NFC_TOKEN; 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "nfc_interface")) 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_NFC_INTERFACE; 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "push_button")) 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_PUSHBUTTON; 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "keypad")) 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_KEYPAD; 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS2 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "virtual_display")) 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_VIRT_DISPLAY; 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "physical_display")) 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_PHY_DISPLAY; 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "virtual_push_button")) 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_VIRT_PUSHBUTTON; 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "physical_push_button")) 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_PHY_PUSHBUTTON; 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS2 */ 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return methods; 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wps_build_wsc_ack(struct wps_data *wps) 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpabuf_alloc(1000); 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_build_version(msg) || 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_msg_type(msg, WPS_WSC_ACK) || 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_enrollee_nonce(wps, msg) || 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_registrar_nonce(wps, msg) || 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_wfa_ext(msg, 0, NULL, 0)) { 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wps_build_wsc_nack(struct wps_data *wps) 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpabuf_alloc(1000); 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_build_version(msg) || 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_msg_type(msg, WPS_WSC_NACK) || 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_enrollee_nonce(wps, msg) || 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_registrar_nonce(wps, msg) || 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_config_error(msg, wps->config_error) || 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_wfa_ext(msg, 0, NULL, 0)) { 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 705