10SN/A/* 2798Sjoehw * Wi-Fi Protected Setup - common functionality 30SN/A * Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi> 40SN/A * 5798Sjoehw * This software may be distributed under the terms of the BSD license. 6798Sjoehw * See README for more details. 7798Sjoehw */ 8798Sjoehw 9798Sjoehw#include "includes.h" 10798Sjoehw 110SN/A#include "common.h" 120SN/A#include "crypto/aes_wrap.h" 130SN/A#include "crypto/crypto.h" 140SN/A#include "crypto/dh_group5.h" 150SN/A#include "crypto/sha1.h" 160SN/A#include "crypto/sha256.h" 170SN/A#include "crypto/random.h" 180SN/A#include "wps_i.h" 190SN/A 200SN/A 210SN/Avoid wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, 220SN/A const char *label, u8 *res, size_t res_len) 230SN/A{ 240SN/A u8 i_buf[4], key_bits[4]; 250SN/A const u8 *addr[4]; 26798Sjoehw size_t len[4]; 270SN/A int i, iter; 280SN/A u8 hash[SHA256_MAC_LEN], *opos; 290SN/A size_t left; 300SN/A 310SN/A WPA_PUT_BE32(key_bits, res_len * 8); 320SN/A 33798Sjoehw addr[0] = i_buf; 340SN/A len[0] = sizeof(i_buf); 350SN/A addr[1] = label_prefix; 360SN/A len[1] = label_prefix_len; 370SN/A addr[2] = (const u8 *) label; 380SN/A len[2] = os_strlen(label); 390SN/A addr[3] = key_bits; 400SN/A len[3] = sizeof(key_bits); 410SN/A 420SN/A iter = (res_len + SHA256_MAC_LEN - 1) / SHA256_MAC_LEN; 430SN/A opos = res; 440SN/A left = res_len; 450SN/A 460SN/A for (i = 1; i <= iter; i++) { 470SN/A WPA_PUT_BE32(i_buf, i); 480SN/A hmac_sha256_vector(key, SHA256_MAC_LEN, 4, addr, len, hash); 490SN/A if (i < iter) { 500SN/A os_memcpy(opos, hash, SHA256_MAC_LEN); 510SN/A opos += SHA256_MAC_LEN; 520SN/A left -= SHA256_MAC_LEN; 530SN/A } else 540SN/A os_memcpy(opos, hash, left); 550SN/A } 560SN/A} 570SN/A 580SN/A 590SN/Aint wps_derive_keys(struct wps_data *wps) 600SN/A{ 610SN/A struct wpabuf *pubkey, *dh_shared; 620SN/A u8 dhkey[SHA256_MAC_LEN], kdk[SHA256_MAC_LEN]; 630SN/A const u8 *addr[3]; 640SN/A size_t len[3]; 650SN/A u8 keys[WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN + WPS_EMSK_LEN]; 660SN/A 670SN/A if (wps->dh_privkey == NULL) { 680SN/A wpa_printf(MSG_DEBUG, "WPS: Own DH private key not available"); 690SN/A return -1; 700SN/A } 710SN/A 720SN/A pubkey = wps->registrar ? wps->dh_pubkey_e : wps->dh_pubkey_r; 730SN/A if (pubkey == NULL) { 740SN/A wpa_printf(MSG_DEBUG, "WPS: Peer DH public key not available"); 750SN/A return -1; 760SN/A } 770SN/A 780SN/A wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); 790SN/A wpa_hexdump_buf(MSG_DEBUG, "WPS: DH peer Public Key", pubkey); 800SN/A dh_shared = dh5_derive_shared(wps->dh_ctx, pubkey, wps->dh_privkey); 810SN/A dh5_free(wps->dh_ctx); 820SN/A wps->dh_ctx = NULL; 830SN/A dh_shared = wpabuf_zeropad(dh_shared, 192); 840SN/A if (dh_shared == NULL) { 850SN/A wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key"); 860SN/A return -1; 870SN/A } 880SN/A 890SN/A /* Own DH private key is not needed anymore */ 900SN/A wpabuf_free(wps->dh_privkey); 910SN/A wps->dh_privkey = NULL; 920SN/A 930SN/A wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH shared key", dh_shared); 940SN/A 950SN/A /* DHKey = SHA-256(g^AB mod p) */ 960SN/A addr[0] = wpabuf_head(dh_shared); 970SN/A len[0] = wpabuf_len(dh_shared); 980SN/A sha256_vector(1, addr, len, dhkey); 990SN/A wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey)); 1000SN/A wpabuf_free(dh_shared); 1010SN/A 1020SN/A /* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */ 1030SN/A addr[0] = wps->nonce_e; 1040SN/A len[0] = WPS_NONCE_LEN; 1050SN/A addr[1] = wps->mac_addr_e; 1060SN/A len[1] = ETH_ALEN; 1070SN/A addr[2] = wps->nonce_r; 1080SN/A len[2] = WPS_NONCE_LEN; 1090SN/A hmac_sha256_vector(dhkey, sizeof(dhkey), 3, addr, len, kdk); 1100SN/A wpa_hexdump_key(MSG_DEBUG, "WPS: KDK", kdk, sizeof(kdk)); 1110SN/A 1120SN/A wps_kdf(kdk, NULL, 0, "Wi-Fi Easy and Secure Key Derivation", 1130SN/A keys, sizeof(keys)); 1140SN/A os_memcpy(wps->authkey, keys, WPS_AUTHKEY_LEN); 1150SN/A os_memcpy(wps->keywrapkey, keys + WPS_AUTHKEY_LEN, WPS_KEYWRAPKEY_LEN); 1160SN/A os_memcpy(wps->emsk, keys + WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN, 1170SN/A WPS_EMSK_LEN); 1180SN/A 1190SN/A wpa_hexdump_key(MSG_DEBUG, "WPS: AuthKey", 1200SN/A wps->authkey, WPS_AUTHKEY_LEN); 1210SN/A wpa_hexdump_key(MSG_DEBUG, "WPS: KeyWrapKey", 1220SN/A wps->keywrapkey, WPS_KEYWRAPKEY_LEN); 1230SN/A wpa_hexdump_key(MSG_DEBUG, "WPS: EMSK", wps->emsk, WPS_EMSK_LEN); 1240SN/A 1250SN/A return 0; 1260SN/A} 1270SN/A 1280SN/A 1290SN/Avoid wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, 1300SN/A size_t dev_passwd_len) 1310SN/A{ 1320SN/A u8 hash[SHA256_MAC_LEN]; 1330SN/A 1340SN/A hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd, 1350SN/A (dev_passwd_len + 1) / 2, hash); 1360SN/A os_memcpy(wps->psk1, hash, WPS_PSK_LEN); 1370SN/A hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, 1380SN/A dev_passwd + (dev_passwd_len + 1) / 2, 1390SN/A dev_passwd_len / 2, hash); 1400SN/A os_memcpy(wps->psk2, hash, WPS_PSK_LEN); 1410SN/A 1420SN/A wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password", 1430SN/A dev_passwd, dev_passwd_len); 1440SN/A wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN); 1450SN/A wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN); 1460SN/A} 1470SN/A 1480SN/A 1490SN/Astruct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, 1500SN/A size_t encr_len) 1510SN/A{ 1520SN/A struct wpabuf *decrypted; 1530SN/A const size_t block_size = 16; 1540SN/A size_t i; 1550SN/A u8 pad; 1560SN/A const u8 *pos; 1570SN/A 1580SN/A /* AES-128-CBC */ 1590SN/A if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size) 1600SN/A { 1610SN/A wpa_printf(MSG_DEBUG, "WPS: No Encrypted Settings received"); 1620SN/A return NULL; 1630SN/A } 1640SN/A 1650SN/A decrypted = wpabuf_alloc(encr_len - block_size); 1660SN/A if (decrypted == NULL) 1670SN/A return NULL; 1680SN/A 1690SN/A wpa_hexdump(MSG_MSGDUMP, "WPS: Encrypted Settings", encr, encr_len); 1700SN/A wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size); 1710SN/A if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted), 1720SN/A wpabuf_len(decrypted))) { 1730SN/A wpabuf_free(decrypted); 1740SN/A return NULL; 1750SN/A } 1760SN/A 1770SN/A wpa_hexdump_buf_key(MSG_MSGDUMP, "WPS: Decrypted Encrypted Settings", 1780SN/A decrypted); 1790SN/A 1800SN/A pos = wpabuf_head_u8(decrypted) + wpabuf_len(decrypted) - 1; 1810SN/A pad = *pos; 1820SN/A if (pad > wpabuf_len(decrypted)) { 1830SN/A wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value"); 1840SN/A wpabuf_free(decrypted); 1850SN/A return NULL; 1860SN/A } 1870SN/A for (i = 0; i < pad; i++) { 1880SN/A if (*pos-- != pad) { 1890SN/A wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad " 1900SN/A "string"); 1910SN/A wpabuf_free(decrypted); 1920SN/A return NULL; 1930SN/A } 1940SN/A } 1950SN/A decrypted->used -= pad; 1960SN/A 1970SN/A return decrypted; 1980SN/A} 1990SN/A 2000SN/A 2010SN/A/** 2020SN/A * wps_pin_checksum - Compute PIN checksum 2030SN/A * @pin: Seven digit PIN (i.e., eight digit PIN without the checksum digit) 2040SN/A * Returns: Checksum digit 2050SN/A */ 2060SN/Aunsigned int wps_pin_checksum(unsigned int pin) 2070SN/A{ 2080SN/A unsigned int accum = 0; 2090SN/A while (pin) { 2100SN/A accum += 3 * (pin % 10); 2110SN/A pin /= 10; 2120SN/A accum += pin % 10; 2130SN/A pin /= 10; 2140SN/A } 2150SN/A 2160SN/A return (10 - accum % 10) % 10; 2170SN/A} 2180SN/A 2190SN/A 2200SN/A/** 2210SN/A * wps_pin_valid - Check whether a PIN has a valid checksum 2220SN/A * @pin: Eight digit PIN (i.e., including the checksum digit) 2230SN/A * Returns: 1 if checksum digit is valid, or 0 if not 2240SN/A */ 2250SN/Aunsigned int wps_pin_valid(unsigned int pin) 2260SN/A{ 2270SN/A return wps_pin_checksum(pin / 10) == (pin % 10); 2280SN/A} 2290SN/A 2300SN/A 2310SN/A/** 2320SN/A * wps_generate_pin - Generate a random PIN 2330SN/A * Returns: Eight digit PIN (i.e., including the checksum digit) 2340SN/A */ 2350SN/Aunsigned int wps_generate_pin(void) 2360SN/A{ 2370SN/A unsigned int val; 2380SN/A 2390SN/A /* Generate seven random digits for the PIN */ 2400SN/A if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) { 2410SN/A struct os_time now; 2420SN/A os_get_time(&now); 2430SN/A val = os_random() ^ now.sec ^ now.usec; 2440SN/A } 2450SN/A val %= 10000000; 2460SN/A 2470SN/A /* Append checksum digit */ 2480SN/A return val * 10 + wps_pin_checksum(val); 2490SN/A} 2500SN/A 2510SN/A 2520SN/Aint wps_pin_str_valid(const char *pin) 2530SN/A{ 2540SN/A const char *p; 2550SN/A size_t len; 2560SN/A 2570SN/A p = pin; 2580SN/A while (*p >= '0' && *p <= '9') 2590SN/A p++; 2600SN/A if (*p != '\0') 2610SN/A return 0; 2620SN/A 2630SN/A len = p - pin; 2640SN/A return len == 4 || len == 8; 2650SN/A} 2660SN/A 2670SN/A 2680SN/Avoid wps_fail_event(struct wps_context *wps, enum wps_msg_type msg, 2690SN/A u16 config_error, u16 error_indication) 2700SN/A{ 2710SN/A union wps_event_data data; 2720SN/A 2730SN/A if (wps->event_cb == NULL) 2740SN/A return; 2750SN/A 2760SN/A os_memset(&data, 0, sizeof(data)); 2770SN/A data.fail.msg = msg; 2780SN/A data.fail.config_error = config_error; 2790SN/A data.fail.error_indication = error_indication; 2800SN/A wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data); 2810SN/A} 2820SN/A 2830SN/A 2840SN/Avoid wps_success_event(struct wps_context *wps) 2850SN/A{ 2860SN/A if (wps->event_cb == NULL) 2870SN/A return; 2880SN/A 2890SN/A wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, NULL); 2900SN/A} 2910SN/A 2920SN/A 2930SN/Avoid wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part) 2940SN/A{ 2950SN/A union wps_event_data data; 2960SN/A 2970SN/A if (wps->event_cb == NULL) 2980SN/A return; 2990SN/A 3000SN/A os_memset(&data, 0, sizeof(data)); 3010SN/A data.pwd_auth_fail.enrollee = enrollee; 3020SN/A data.pwd_auth_fail.part = part; 3030SN/A wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, &data); 3040SN/A} 3050SN/A 3060SN/A 3070SN/Avoid wps_pbc_overlap_event(struct wps_context *wps) 3080SN/A{ 3090SN/A if (wps->event_cb == NULL) 3100SN/A return; 3110SN/A 3120SN/A wps->event_cb(wps->cb_ctx, WPS_EV_PBC_OVERLAP, NULL); 3130SN/A} 3140SN/A 3150SN/A 3160SN/Avoid wps_pbc_timeout_event(struct wps_context *wps) 3170SN/A{ 3180SN/A if (wps->event_cb == NULL) 3190SN/A return; 3200SN/A 3210SN/A wps->event_cb(wps->cb_ctx, WPS_EV_PBC_TIMEOUT, NULL); 3220SN/A} 3230SN/A 3240SN/A 3250SN/A#ifdef CONFIG_WPS_OOB 3260SN/A 3270SN/Astruct wpabuf * wps_get_oob_cred(struct wps_context *wps) 3280SN/A{ 3290SN/A struct wps_data data; 3300SN/A struct wpabuf *plain; 3310SN/A 3320SN/A plain = wpabuf_alloc(500); 3330SN/A if (plain == NULL) { 3340SN/A wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " 3350SN/A "credential"); 3360SN/A return NULL; 3370SN/A } 3380SN/A 3390SN/A os_memset(&data, 0, sizeof(data)); 3400SN/A data.wps = wps; 3410SN/A data.auth_type = wps->auth_types; 3420SN/A data.encr_type = wps->encr_types; 3430SN/A if (wps_build_version(plain) || 3440SN/A wps_build_cred(&data, plain) || 3450SN/A wps_build_wfa_ext(plain, 0, NULL, 0)) { 3460SN/A wpabuf_free(plain); 3470SN/A return NULL; 3480SN/A } 3490SN/A 3500SN/A return plain; 3510SN/A} 3520SN/A 3530SN/A 3540SN/Astruct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id, 3550SN/A const struct wpabuf *pubkey, 3560SN/A const struct wpabuf *dev_pw) 3570SN/A{ 3580SN/A struct wpabuf *data; 3590SN/A 3600SN/A data = wpabuf_alloc(200); 3610SN/A if (data == NULL) 3620SN/A return NULL; 3630SN/A 3640SN/A if (wps_build_version(data) || 3650SN/A wps_build_oob_dev_pw(data, dev_pw_id, pubkey, 3660SN/A wpabuf_head(dev_pw), wpabuf_len(dev_pw)) || 3670SN/A wps_build_wfa_ext(data, 0, NULL, 0)) { 3680SN/A wpa_printf(MSG_ERROR, "WPS: Failed to build NFC password " 3690SN/A "token"); 3700SN/A wpabuf_free(data); 3710SN/A return NULL; 3720SN/A } 3730SN/A 3740SN/A return data; 3750SN/A} 3760SN/A 3770SN/A 3780SN/Aint wps_oob_use_cred(struct wps_context *wps, struct wps_parse_attr *attr) 3790SN/A{ 3800SN/A struct wpabuf msg; 3810SN/A size_t i; 3820SN/A 3830SN/A for (i = 0; i < attr->num_cred; i++) { 3840SN/A struct wps_credential local_cred; 3850SN/A struct wps_parse_attr cattr; 3860SN/A 3870SN/A os_memset(&local_cred, 0, sizeof(local_cred)); 3880SN/A wpabuf_set(&msg, attr->cred[i], attr->cred_len[i]); 3890SN/A if (wps_parse_msg(&msg, &cattr) < 0 || 3900SN/A wps_process_cred(&cattr, &local_cred)) { 3910SN/A wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB " 3920SN/A "credential"); 3930SN/A return -1; 3940SN/A } 3950SN/A wps->cred_cb(wps->cb_ctx, &local_cred); 3960SN/A } 3970SN/A 3980SN/A return 0; 3990SN/A} 4000SN/A 4010SN/A 4020SN/A#endif /* CONFIG_WPS_OOB */ 4030SN/A 4040SN/A 4050SN/Aint wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]) 4060SN/A{ 4070SN/A const char *pos; 4080SN/A 4090SN/A /* <categ>-<OUI>-<subcateg> */ 4100SN/A WPA_PUT_BE16(dev_type, atoi(str)); 4110SN/A pos = os_strchr(str, '-'); 4120SN/A if (pos == NULL) 4130SN/A return -1; 4140SN/A pos++; 4150SN/A if (hexstr2bin(pos, &dev_type[2], 4)) 4160SN/A return -1; 4170SN/A pos = os_strchr(pos, '-'); 4180SN/A if (pos == NULL) 4190SN/A return -1; 4200SN/A pos++; 4210SN/A WPA_PUT_BE16(&dev_type[6], atoi(pos)); 4220SN/A 4230SN/A 4240SN/A return 0; 4250SN/A} 4260SN/A 4270SN/A 4280SN/Achar * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf, 4290SN/A size_t buf_len) 4300SN/A{ 4310SN/A int ret; 4320SN/A 4330SN/A ret = os_snprintf(buf, buf_len, "%u-%08X-%u", 4340SN/A WPA_GET_BE16(dev_type), WPA_GET_BE32(&dev_type[2]), 4350SN/A WPA_GET_BE16(&dev_type[6])); 4360SN/A if (ret < 0 || (unsigned int) ret >= buf_len) 4370SN/A return NULL; 4380SN/A 4390SN/A return buf; 4400SN/A} 4410SN/A 4420SN/A 4430SN/Avoid uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid) 4440SN/A{ 4450SN/A const u8 *addr[2]; 4460SN/A size_t len[2]; 4470SN/A u8 hash[SHA1_MAC_LEN]; 4480SN/A u8 nsid[16] = { 4490SN/A 0x52, 0x64, 0x80, 0xf8, 4500SN/A 0xc9, 0x9b, 4510SN/A 0x4b, 0xe5, 4520SN/A 0xa6, 0x55, 4530SN/A 0x58, 0xed, 0x5f, 0x5d, 0x60, 0x84 4540SN/A }; 4550SN/A 4560SN/A addr[0] = nsid; 4570SN/A len[0] = sizeof(nsid); 4580SN/A addr[1] = mac_addr; 4590SN/A len[1] = 6; 4600SN/A sha1_vector(2, addr, len, hash); 4610SN/A os_memcpy(uuid, hash, 16); 4620SN/A 4630SN/A /* Version: 5 = named-based version using SHA-1 */ 4640SN/A uuid[6] = (5 << 4) | (uuid[6] & 0x0f); 4650SN/A 4660SN/A /* Variant specified in RFC 4122 */ 4670SN/A uuid[8] = 0x80 | (uuid[8] & 0x3f); 4680SN/A} 4690SN/A 4700SN/A 4710SN/Au16 wps_config_methods_str2bin(const char *str) 4720SN/A{ 4730SN/A u16 methods = 0; 4740SN/A 4750SN/A if (str == NULL) { 4760SN/A /* Default to enabling methods based on build configuration */ 4770SN/A methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; 4780SN/A#ifdef CONFIG_WPS2 4790SN/A methods |= WPS_CONFIG_VIRT_DISPLAY; 4800SN/A#endif /* CONFIG_WPS2 */ 4810SN/A#ifdef CONFIG_WPS_NFC 4820SN/A methods |= WPS_CONFIG_NFC_INTERFACE; 4830SN/A#endif /* CONFIG_WPS_NFC */ 4840SN/A } else { 4850SN/A if (os_strstr(str, "ethernet")) 4860SN/A methods |= WPS_CONFIG_ETHERNET; 4870SN/A if (os_strstr(str, "label")) 4880SN/A methods |= WPS_CONFIG_LABEL; 4890SN/A if (os_strstr(str, "display")) 4900SN/A methods |= WPS_CONFIG_DISPLAY; 4910SN/A if (os_strstr(str, "ext_nfc_token")) 4920SN/A methods |= WPS_CONFIG_EXT_NFC_TOKEN; 4930SN/A if (os_strstr(str, "int_nfc_token")) 4940SN/A methods |= WPS_CONFIG_INT_NFC_TOKEN; 4950SN/A if (os_strstr(str, "nfc_interface")) 4960SN/A methods |= WPS_CONFIG_NFC_INTERFACE; 4970SN/A if (os_strstr(str, "push_button")) 4980SN/A methods |= WPS_CONFIG_PUSHBUTTON; 4990SN/A if (os_strstr(str, "keypad")) 5000SN/A methods |= WPS_CONFIG_KEYPAD; 5010SN/A#ifdef CONFIG_WPS2 5020SN/A if (os_strstr(str, "virtual_display")) 5030SN/A methods |= WPS_CONFIG_VIRT_DISPLAY; 5040SN/A if (os_strstr(str, "physical_display")) 5050SN/A methods |= WPS_CONFIG_PHY_DISPLAY; 5060SN/A if (os_strstr(str, "virtual_push_button")) 5070SN/A methods |= WPS_CONFIG_VIRT_PUSHBUTTON; 5080SN/A if (os_strstr(str, "physical_push_button")) 5090SN/A methods |= WPS_CONFIG_PHY_PUSHBUTTON; 5100SN/A#endif /* CONFIG_WPS2 */ 5110SN/A } 5120SN/A 5130SN/A return methods; 5140SN/A} 5150SN/A 5160SN/A 5170SN/Astruct wpabuf * wps_build_wsc_ack(struct wps_data *wps) 5180SN/A{ 5190SN/A struct wpabuf *msg; 5200SN/A 5210SN/A wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); 5220SN/A 5230SN/A msg = wpabuf_alloc(1000); 5240SN/A if (msg == NULL) 5250SN/A return NULL; 5260SN/A 5270SN/A if (wps_build_version(msg) || 5280SN/A wps_build_msg_type(msg, WPS_WSC_ACK) || 5290SN/A wps_build_enrollee_nonce(wps, msg) || 5300SN/A wps_build_registrar_nonce(wps, msg) || 5310SN/A wps_build_wfa_ext(msg, 0, NULL, 0)) { 5320SN/A wpabuf_free(msg); 5330SN/A return NULL; 5340SN/A } 5350SN/A 5360SN/A return msg; 5370SN/A} 5380SN/A 5390SN/A 5400SN/Astruct wpabuf * wps_build_wsc_nack(struct wps_data *wps) 5410SN/A{ 5420SN/A struct wpabuf *msg; 5430SN/A 5440SN/A wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); 5450SN/A 5460SN/A msg = wpabuf_alloc(1000); 5470SN/A if (msg == NULL) 5480SN/A return NULL; 5490SN/A 5500SN/A if (wps_build_version(msg) || 5510SN/A wps_build_msg_type(msg, WPS_WSC_NACK) || 5520SN/A wps_build_enrollee_nonce(wps, msg) || 5530SN/A wps_build_registrar_nonce(wps, msg) || 5540SN/A wps_build_config_error(msg, wps->config_error) || 5550SN/A wps_build_wfa_ext(msg, 0, NULL, 0)) { 5560SN/A wpabuf_free(msg); 5570SN/A return NULL; 5580SN/A } 5590SN/A 5600SN/A return msg; 5610SN/A} 5620SN/A 5630SN/A 5640SN/A#ifdef CONFIG_WPS_NFC 5650SN/Astruct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey, 5660SN/A struct wpabuf **privkey, 5670SN/A struct wpabuf **dev_pw) 5680SN/A{ 5690SN/A struct wpabuf *priv = NULL, *pub = NULL, *pw, *ret; 5700SN/A void *dh_ctx; 5710SN/A u16 val; 5720SN/A 5730SN/A pw = wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN); 5740SN/A if (pw == NULL) 5750SN/A return NULL; 5760SN/A 5770SN/A if (random_get_bytes(wpabuf_put(pw, WPS_OOB_DEVICE_PASSWORD_LEN), 5780SN/A WPS_OOB_DEVICE_PASSWORD_LEN) || 5790SN/A random_get_bytes((u8 *) &val, sizeof(val))) { 5800SN/A wpabuf_free(pw); 5810SN/A return NULL; 5820SN/A } 5830SN/A 5840SN/A dh_ctx = dh5_init(&priv, &pub); 5850SN/A if (dh_ctx == NULL) { 5860SN/A wpabuf_free(pw); 5870SN/A return NULL; 5880SN/A } 5890SN/A dh5_free(dh_ctx); 5900SN/A 5910SN/A *id = 0x10 + val % 0xfff0; 5920SN/A wpabuf_free(*pubkey); 5930SN/A *pubkey = pub; 5940SN/A wpabuf_free(*privkey); 5950SN/A *privkey = priv; 5960SN/A wpabuf_free(*dev_pw); 5970SN/A *dev_pw = pw; 5980SN/A 5990SN/A ret = wps_build_nfc_pw_token(*id, *pubkey, *dev_pw); 6000SN/A if (ndef && ret) { 6010SN/A struct wpabuf *tmp; 6020SN/A tmp = ndef_build_wifi(ret); 6030SN/A wpabuf_free(ret); 6040SN/A if (tmp == NULL) 6050SN/A return NULL; 6060SN/A ret = tmp; 6070SN/A } 6080SN/A 6090SN/A return ret; 6100SN/A} 6110SN/A#endif /* CONFIG_WPS_NFC */ 6120SN/A