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" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/aes_wrap.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/dh_group5.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha256.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_i.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *label, u8 *res, size_t res_len) 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 i_buf[4], key_bits[4]; 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[4]; 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[4]; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, iter; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA256_MAC_LEN], *opos; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE32(key_bits, res_len * 8); 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = i_buf; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = sizeof(i_buf); 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = label_prefix; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = label_prefix_len; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = (const u8 *) label; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[2] = os_strlen(label); 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[3] = key_bits; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[3] = sizeof(key_bits); 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iter = (res_len + SHA256_MAC_LEN - 1) / SHA256_MAC_LEN; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt opos = res; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = res_len; 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 1; i <= iter; i++) { 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE32(i_buf, i); 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256_vector(key, SHA256_MAC_LEN, 4, addr, len, hash); 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (i < iter) { 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(opos, hash, SHA256_MAC_LEN); 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt opos += SHA256_MAC_LEN; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= SHA256_MAC_LEN; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(opos, hash, left); 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_derive_keys(struct wps_data *wps) 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *pubkey, *dh_shared; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dhkey[SHA256_MAC_LEN], kdk[SHA256_MAC_LEN]; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[3]; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[3]; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 keys[WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN + WPS_EMSK_LEN]; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->dh_privkey == NULL) { 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Own DH private key not available"); 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pubkey = wps->registrar ? wps->dh_pubkey_e : wps->dh_pubkey_r; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pubkey == NULL) { 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Peer DH public key not available"); 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "WPS: DH peer Public Key", pubkey); 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dh_shared = dh5_derive_shared(wps->dh_ctx, pubkey, wps->dh_privkey); 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dh5_free(wps->dh_ctx); 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->dh_ctx = NULL; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dh_shared = wpabuf_zeropad(dh_shared, 192); 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dh_shared == NULL) { 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key"); 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Own DH private key is not needed anymore */ 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(wps->dh_privkey); 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->dh_privkey = NULL; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH shared key", dh_shared); 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* DHKey = SHA-256(g^AB mod p) */ 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = wpabuf_head(dh_shared); 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = wpabuf_len(dh_shared); 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(1, addr, len, dhkey); 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey)); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(dh_shared); 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */ 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = wps->nonce_e; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = WPS_NONCE_LEN; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = wps->mac_addr_e; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = ETH_ALEN; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[2] = wps->nonce_r; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[2] = WPS_NONCE_LEN; 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256_vector(dhkey, sizeof(dhkey), 3, addr, len, kdk); 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: KDK", kdk, sizeof(kdk)); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_kdf(kdk, NULL, 0, "Wi-Fi Easy and Secure Key Derivation", 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys, sizeof(keys)); 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wps->authkey, keys, WPS_AUTHKEY_LEN); 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wps->keywrapkey, keys + WPS_AUTHKEY_LEN, WPS_KEYWRAPKEY_LEN); 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wps->emsk, keys + WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN, 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPS_EMSK_LEN); 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: AuthKey", 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->authkey, WPS_AUTHKEY_LEN); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: KeyWrapKey", 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->keywrapkey, WPS_KEYWRAPKEY_LEN); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: EMSK", wps->emsk, WPS_EMSK_LEN); 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t dev_passwd_len) 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA256_MAC_LEN]; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd, 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (dev_passwd_len + 1) / 2, hash); 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wps->psk1, hash, WPS_PSK_LEN); 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev_passwd + (dev_passwd_len + 1) / 2, 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev_passwd_len / 2, hash); 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wps->psk2, hash, WPS_PSK_LEN); 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password", 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dev_passwd, dev_passwd_len); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN); 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN); 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t encr_len) 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *decrypted; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const size_t block_size = 16; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 pad; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* AES-128-CBC */ 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size) 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: No Encrypted Settings received"); 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = wpabuf_alloc(encr_len - block_size); 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "WPS: Encrypted Settings", encr, encr_len); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size); 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted), 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(decrypted))) { 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(decrypted); 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf_key(MSG_MSGDUMP, "WPS: Decrypted Encrypted Settings", 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted); 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpabuf_head_u8(decrypted) + wpabuf_len(decrypted) - 1; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad = *pos; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pad > wpabuf_len(decrypted)) { 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value"); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(decrypted); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < pad; i++) { 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos-- != pad) { 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad " 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "string"); 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(decrypted); 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted->used -= pad; 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return decrypted; 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wps_pin_checksum - Compute PIN checksum 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pin: Seven digit PIN (i.e., eight digit PIN without the checksum digit) 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Checksum digit 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int wps_pin_checksum(unsigned int pin) 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int accum = 0; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pin) { 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt accum += 3 * (pin % 10); 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pin /= 10; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt accum += pin % 10; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pin /= 10; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return (10 - accum % 10) % 10; 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wps_pin_valid - Check whether a PIN has a valid checksum 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pin: Eight digit PIN (i.e., including the checksum digit) 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 if checksum digit is valid, or 0 if not 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int wps_pin_valid(unsigned int pin) 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wps_pin_checksum(pin / 10) == (pin % 10); 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wps_generate_pin - Generate a random PIN 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Eight digit PIN (i.e., including the checksum digit) 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int wps_generate_pin(void) 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int val; 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Generate seven random digits for the PIN */ 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) { 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct os_time now; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_get_time(&now); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = os_random() ^ now.sec ^ now.usec; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val %= 10000000; 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Append checksum digit */ 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return val * 10 + wps_pin_checksum(val); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint wps_pin_str_valid(const char *pin) 25304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 25404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const char *p; 25504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt size_t len; 25604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 25704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt p = pin; 25804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt while (*p >= '0' && *p <= '9') 25904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt p++; 26004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (*p != '\0') 26104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 26204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 26304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt len = p - pin; 26404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return len == 4 || len == 8; 26504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 26604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 26704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_fail_event(struct wps_context *wps, enum wps_msg_type msg, 269b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt u16 config_error, u16 error_indication, const u8 *mac_addr) 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wps_event_data data; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.fail.msg = msg; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.fail.config_error = config_error; 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.fail.error_indication = error_indication; 280b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt os_memcpy(data.fail.peer_macaddr, mac_addr, ETH_ALEN); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data); 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 285b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtvoid wps_success_event(struct wps_context *wps, const u8 *mac_addr) 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 287b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt union wps_event_data data; 288b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 292b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 293b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt os_memcpy(data.success.peer_macaddr, mac_addr, ETH_ALEN); 294b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, &data); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 298b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtvoid wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part, 299b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt const u8 *mac_addr) 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wps_event_data data; 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.pwd_auth_fail.enrollee = enrollee; 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.pwd_auth_fail.part = part; 309b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt os_memcpy(data.pwd_auth_fail.peer_macaddr, mac_addr, ETH_ALEN); 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, &data); 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_pbc_overlap_event(struct wps_context *wps) 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PBC_OVERLAP, NULL); 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_pbc_timeout_event(struct wps_context *wps) 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps->event_cb == NULL) 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PBC_TIMEOUT, NULL); 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 332b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtvoid wps_pbc_active_event(struct wps_context *wps) 333b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 334b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (wps->event_cb == NULL) 335b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return; 336b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 337b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PBC_ACTIVE, NULL); 338b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 339b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 340b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 341b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtvoid wps_pbc_disable_event(struct wps_context *wps) 342b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 343b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (wps->event_cb == NULL) 344b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return; 345b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 346b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt wps->event_cb(wps->cb_ctx, WPS_EV_PBC_DISABLE, NULL); 347b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 348b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 349b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_OOB 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35204949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstruct wpabuf * wps_get_oob_cred(struct wps_context *wps) 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_data data; 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *plain; 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plain = wpabuf_alloc(500); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (plain == NULL) { 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "credential"); 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.wps = wps; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.auth_type = wps->auth_types; 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.encr_type = wps->encr_types; 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_build_version(plain) || 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_cred(&data, plain) || 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_wfa_ext(plain, 0, NULL, 0)) { 3714b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_free(data.new_psk); 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(plain); 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3764b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt if (wps->wps_state == WPS_STATE_NOT_CONFIGURED && data.new_psk && 3774b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wps->ap) { 3784b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt struct wps_credential cred; 3794b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 3804b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based " 3814b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt "on credential token generation"); 3824b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 3834b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_memset(&cred, 0, sizeof(cred)); 3844b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_memcpy(cred.ssid, wps->ssid, wps->ssid_len); 3854b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt cred.ssid_len = wps->ssid_len; 3864b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK; 3874b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES; 3884b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_memcpy(cred.key, data.new_psk, data.new_psk_len); 3894b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt cred.key_len = data.new_psk_len; 3904b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 3914b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wps->wps_state = WPS_STATE_CONFIGURED; 3924b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wpa_hexdump_ascii_key(MSG_DEBUG, 3934b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt "WPS: Generated random passphrase", 3944b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt data.new_psk, data.new_psk_len); 3954b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt if (wps->cred_cb) 3964b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt wps->cred_cb(wps->cb_ctx, &cred); 3974b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt } 3984b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 3994b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_free(data.new_psk); 4004b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return plain; 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstruct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id, 40604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const struct wpabuf *pubkey, 40704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const struct wpabuf *dev_pw) 40804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 40904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf *data; 41004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 41104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt data = wpabuf_alloc(200); 41204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (data == NULL) 41304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 41404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 41504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wps_build_version(data) || 41604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wps_build_oob_dev_pw(data, dev_pw_id, pubkey, 41704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_head(dev_pw), wpabuf_len(dev_pw)) || 41804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wps_build_wfa_ext(data, 0, NULL, 0)) { 41904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Failed to build NFC password " 42004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "token"); 42104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(data); 42204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 42304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 42404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 42504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return data; 42604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 42704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 42804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 42904949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint wps_oob_use_cred(struct wps_context *wps, struct wps_parse_attr *attr) 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf msg; 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = 0; i < attr->num_cred; i++) { 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_credential local_cred; 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wps_parse_attr cattr; 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&local_cred, 0, sizeof(local_cred)); 43904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_set(&msg, attr->cred[i], attr->cred_len[i]); 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_parse_msg(&msg, &cattr) < 0 || 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_process_cred(&cattr, &local_cred)) { 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB " 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "credential"); 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps->cred_cb(wps->cb_ctx, &local_cred); 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_OOB */ 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]) 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *pos; 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* <categ>-<OUI>-<subcateg> */ 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(dev_type, atoi(str)); 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(str, '-'); 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hexstr2bin(pos, &dev_type[2], 4)) 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(pos, '-'); 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(&dev_type[6], atoi(pos)); 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtchar * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf, 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len) 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(buf, buf_len, "%u-%08X-%u", 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(dev_type), WPA_GET_BE32(&dev_type[2]), 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(&dev_type[6])); 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || (unsigned int) ret >= buf_len) 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid) 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[2]; 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[2]; 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[SHA1_MAC_LEN]; 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 nsid[16] = { 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x52, 0x64, 0x80, 0xf8, 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0xc9, 0x9b, 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x4b, 0xe5, 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0xa6, 0x55, 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x58, 0xed, 0x5f, 0x5d, 0x60, 0x84 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = nsid; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = sizeof(nsid); 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = mac_addr; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = 6; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha1_vector(2, addr, len, hash); 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(uuid, hash, 16); 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Version: 5 = named-based version using SHA-1 */ 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uuid[6] = (5 << 4) | (uuid[6] & 0x0f); 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Variant specified in RFC 4122 */ 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uuid[8] = 0x80 | (uuid[8] & 0x3f); 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu16 wps_config_methods_str2bin(const char *str) 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 methods = 0; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (str == NULL) { 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Default to enabling methods based on build configuration */ 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS2 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_VIRT_DISPLAY; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS2 */ 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_NFC 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_NFC_INTERFACE; 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_NFC */ 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "ethernet")) 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_ETHERNET; 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "label")) 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_LABEL; 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "display")) 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_DISPLAY; 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "ext_nfc_token")) 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_EXT_NFC_TOKEN; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "int_nfc_token")) 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_INT_NFC_TOKEN; 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "nfc_interface")) 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_NFC_INTERFACE; 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "push_button")) 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_PUSHBUTTON; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "keypad")) 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_KEYPAD; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS2 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "virtual_display")) 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_VIRT_DISPLAY; 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "physical_display")) 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_PHY_DISPLAY; 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "virtual_push_button")) 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_VIRT_PUSHBUTTON; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(str, "physical_push_button")) 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt methods |= WPS_CONFIG_PHY_PUSHBUTTON; 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS2 */ 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return methods; 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wps_build_wsc_ack(struct wps_data *wps) 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpabuf_alloc(1000); 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_build_version(msg) || 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_msg_type(msg, WPS_WSC_ACK) || 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_enrollee_nonce(wps, msg) || 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_registrar_nonce(wps, msg) || 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_wfa_ext(msg, 0, NULL, 0)) { 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * wps_build_wsc_nack(struct wps_data *wps) 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpabuf_alloc(1000); 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_build_version(msg) || 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_msg_type(msg, WPS_WSC_NACK) || 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_enrollee_nonce(wps, msg) || 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_registrar_nonce(wps, msg) || 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_config_error(msg, wps->config_error) || 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_build_wfa_ext(msg, 0, NULL, 0)) { 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 61304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 61404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 61504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_WPS_NFC 616f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 617f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtstruct wpabuf * wps_nfc_token_build(int ndef, int id, struct wpabuf *pubkey, 618f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpabuf *dev_pw) 619f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{ 620f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpabuf *ret; 621f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 622f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (pubkey == NULL || dev_pw == NULL) 623f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return NULL; 624f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 625f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt ret = wps_build_nfc_pw_token(id, pubkey, dev_pw); 626f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (ndef && ret) { 627f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpabuf *tmp; 628f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt tmp = ndef_build_wifi(ret); 629f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpabuf_free(ret); 630f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt if (tmp == NULL) 631f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return NULL; 632f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt ret = tmp; 633f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 634f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 635f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return ret; 636f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt} 637f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 638f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 63904949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstruct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey, 64004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf **privkey, 64104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf **dev_pw) 64204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 643f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt struct wpabuf *priv = NULL, *pub = NULL, *pw; 64404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt void *dh_ctx; 64504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u16 val; 64604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 64704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pw = wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN); 64804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (pw == NULL) 64904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 65004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 65104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (random_get_bytes(wpabuf_put(pw, WPS_OOB_DEVICE_PASSWORD_LEN), 65204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt WPS_OOB_DEVICE_PASSWORD_LEN) || 65304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt random_get_bytes((u8 *) &val, sizeof(val))) { 65404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(pw); 65504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 65604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 65704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 65804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dh_ctx = dh5_init(&priv, &pub); 65904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (dh_ctx == NULL) { 66004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(pw); 66104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 66204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 66304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dh5_free(dh_ctx); 66404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 66504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *id = 0x10 + val % 0xfff0; 66604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(*pubkey); 66704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *pubkey = pub; 66804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(*privkey); 66904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *privkey = priv; 67004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(*dev_pw); 67104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt *dev_pw = pw; 67204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 673f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt return wps_nfc_token_build(ndef, *id, *pubkey, *dev_pw); 67404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 675f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 67604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_WPS_NFC */ 677