Home | History | Annotate | Download | only in wps
      1 /*
      2  * Wi-Fi Protected Setup - common functionality
      3  * Copyright (c) 2008-2009, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "includes.h"
     10 
     11 #include "common.h"
     12 #include "crypto/aes_wrap.h"
     13 #include "crypto/crypto.h"
     14 #include "crypto/dh_group5.h"
     15 #include "crypto/sha1.h"
     16 #include "crypto/sha256.h"
     17 #include "crypto/random.h"
     18 #include "wps_i.h"
     19 
     20 
     21 void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len,
     22 	     const char *label, u8 *res, size_t res_len)
     23 {
     24 	u8 i_buf[4], key_bits[4];
     25 	const u8 *addr[4];
     26 	size_t len[4];
     27 	int i, iter;
     28 	u8 hash[SHA256_MAC_LEN], *opos;
     29 	size_t left;
     30 
     31 	WPA_PUT_BE32(key_bits, res_len * 8);
     32 
     33 	addr[0] = i_buf;
     34 	len[0] = sizeof(i_buf);
     35 	addr[1] = label_prefix;
     36 	len[1] = label_prefix_len;
     37 	addr[2] = (const u8 *) label;
     38 	len[2] = os_strlen(label);
     39 	addr[3] = key_bits;
     40 	len[3] = sizeof(key_bits);
     41 
     42 	iter = (res_len + SHA256_MAC_LEN - 1) / SHA256_MAC_LEN;
     43 	opos = res;
     44 	left = res_len;
     45 
     46 	for (i = 1; i <= iter; i++) {
     47 		WPA_PUT_BE32(i_buf, i);
     48 		hmac_sha256_vector(key, SHA256_MAC_LEN, 4, addr, len, hash);
     49 		if (i < iter) {
     50 			os_memcpy(opos, hash, SHA256_MAC_LEN);
     51 			opos += SHA256_MAC_LEN;
     52 			left -= SHA256_MAC_LEN;
     53 		} else
     54 			os_memcpy(opos, hash, left);
     55 	}
     56 }
     57 
     58 
     59 int wps_derive_keys(struct wps_data *wps)
     60 {
     61 	struct wpabuf *pubkey, *dh_shared;
     62 	u8 dhkey[SHA256_MAC_LEN], kdk[SHA256_MAC_LEN];
     63 	const u8 *addr[3];
     64 	size_t len[3];
     65 	u8 keys[WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN + WPS_EMSK_LEN];
     66 
     67 	if (wps->dh_privkey == NULL) {
     68 		wpa_printf(MSG_DEBUG, "WPS: Own DH private key not available");
     69 		return -1;
     70 	}
     71 
     72 	pubkey = wps->registrar ? wps->dh_pubkey_e : wps->dh_pubkey_r;
     73 	if (pubkey == NULL) {
     74 		wpa_printf(MSG_DEBUG, "WPS: Peer DH public key not available");
     75 		return -1;
     76 	}
     77 
     78 	wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey);
     79 	wpa_hexdump_buf(MSG_DEBUG, "WPS: DH peer Public Key", pubkey);
     80 	dh_shared = dh5_derive_shared(wps->dh_ctx, pubkey, wps->dh_privkey);
     81 	dh5_free(wps->dh_ctx);
     82 	wps->dh_ctx = NULL;
     83 	dh_shared = wpabuf_zeropad(dh_shared, 192);
     84 	if (dh_shared == NULL) {
     85 		wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key");
     86 		return -1;
     87 	}
     88 
     89 	/* Own DH private key is not needed anymore */
     90 	wpabuf_free(wps->dh_privkey);
     91 	wps->dh_privkey = NULL;
     92 
     93 	wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH shared key", dh_shared);
     94 
     95 	/* DHKey = SHA-256(g^AB mod p) */
     96 	addr[0] = wpabuf_head(dh_shared);
     97 	len[0] = wpabuf_len(dh_shared);
     98 	sha256_vector(1, addr, len, dhkey);
     99 	wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey));
    100 	wpabuf_free(dh_shared);
    101 
    102 	/* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */
    103 	addr[0] = wps->nonce_e;
    104 	len[0] = WPS_NONCE_LEN;
    105 	addr[1] = wps->mac_addr_e;
    106 	len[1] = ETH_ALEN;
    107 	addr[2] = wps->nonce_r;
    108 	len[2] = WPS_NONCE_LEN;
    109 	hmac_sha256_vector(dhkey, sizeof(dhkey), 3, addr, len, kdk);
    110 	wpa_hexdump_key(MSG_DEBUG, "WPS: KDK", kdk, sizeof(kdk));
    111 
    112 	wps_kdf(kdk, NULL, 0, "Wi-Fi Easy and Secure Key Derivation",
    113 		keys, sizeof(keys));
    114 	os_memcpy(wps->authkey, keys, WPS_AUTHKEY_LEN);
    115 	os_memcpy(wps->keywrapkey, keys + WPS_AUTHKEY_LEN, WPS_KEYWRAPKEY_LEN);
    116 	os_memcpy(wps->emsk, keys + WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN,
    117 		  WPS_EMSK_LEN);
    118 
    119 	wpa_hexdump_key(MSG_DEBUG, "WPS: AuthKey",
    120 			wps->authkey, WPS_AUTHKEY_LEN);
    121 	wpa_hexdump_key(MSG_DEBUG, "WPS: KeyWrapKey",
    122 			wps->keywrapkey, WPS_KEYWRAPKEY_LEN);
    123 	wpa_hexdump_key(MSG_DEBUG, "WPS: EMSK", wps->emsk, WPS_EMSK_LEN);
    124 
    125 	return 0;
    126 }
    127 
    128 
    129 void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
    130 		    size_t dev_passwd_len)
    131 {
    132 	u8 hash[SHA256_MAC_LEN];
    133 
    134 	hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd,
    135 		    (dev_passwd_len + 1) / 2, hash);
    136 	os_memcpy(wps->psk1, hash, WPS_PSK_LEN);
    137 	hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN,
    138 		    dev_passwd + (dev_passwd_len + 1) / 2,
    139 		    dev_passwd_len / 2, hash);
    140 	os_memcpy(wps->psk2, hash, WPS_PSK_LEN);
    141 
    142 	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password",
    143 			      dev_passwd, dev_passwd_len);
    144 	wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN);
    145 	wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN);
    146 }
    147 
    148 
    149 struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
    150 					  size_t encr_len)
    151 {
    152 	struct wpabuf *decrypted;
    153 	const size_t block_size = 16;
    154 	size_t i;
    155 	u8 pad;
    156 	const u8 *pos;
    157 
    158 	/* AES-128-CBC */
    159 	if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size)
    160 	{
    161 		wpa_printf(MSG_DEBUG, "WPS: No Encrypted Settings received");
    162 		return NULL;
    163 	}
    164 
    165 	decrypted = wpabuf_alloc(encr_len - block_size);
    166 	if (decrypted == NULL)
    167 		return NULL;
    168 
    169 	wpa_hexdump(MSG_MSGDUMP, "WPS: Encrypted Settings", encr, encr_len);
    170 	wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size);
    171 	if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted),
    172 				wpabuf_len(decrypted))) {
    173 		wpabuf_free(decrypted);
    174 		return NULL;
    175 	}
    176 
    177 	wpa_hexdump_buf_key(MSG_MSGDUMP, "WPS: Decrypted Encrypted Settings",
    178 			    decrypted);
    179 
    180 	pos = wpabuf_head_u8(decrypted) + wpabuf_len(decrypted) - 1;
    181 	pad = *pos;
    182 	if (pad > wpabuf_len(decrypted)) {
    183 		wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value");
    184 		wpabuf_free(decrypted);
    185 		return NULL;
    186 	}
    187 	for (i = 0; i < pad; i++) {
    188 		if (*pos-- != pad) {
    189 			wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad "
    190 				   "string");
    191 			wpabuf_free(decrypted);
    192 			return NULL;
    193 		}
    194 	}
    195 	decrypted->used -= pad;
    196 
    197 	return decrypted;
    198 }
    199 
    200 
    201 /**
    202  * wps_pin_checksum - Compute PIN checksum
    203  * @pin: Seven digit PIN (i.e., eight digit PIN without the checksum digit)
    204  * Returns: Checksum digit
    205  */
    206 unsigned int wps_pin_checksum(unsigned int pin)
    207 {
    208 	unsigned int accum = 0;
    209 	while (pin) {
    210 		accum += 3 * (pin % 10);
    211 		pin /= 10;
    212 		accum += pin % 10;
    213 		pin /= 10;
    214 	}
    215 
    216 	return (10 - accum % 10) % 10;
    217 }
    218 
    219 
    220 /**
    221  * wps_pin_valid - Check whether a PIN has a valid checksum
    222  * @pin: Eight digit PIN (i.e., including the checksum digit)
    223  * Returns: 1 if checksum digit is valid, or 0 if not
    224  */
    225 unsigned int wps_pin_valid(unsigned int pin)
    226 {
    227 	return wps_pin_checksum(pin / 10) == (pin % 10);
    228 }
    229 
    230 
    231 /**
    232  * wps_generate_pin - Generate a random PIN
    233  * Returns: Eight digit PIN (i.e., including the checksum digit)
    234  */
    235 unsigned int wps_generate_pin(void)
    236 {
    237 	unsigned int val;
    238 
    239 	/* Generate seven random digits for the PIN */
    240 	if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) {
    241 		struct os_time now;
    242 		os_get_time(&now);
    243 		val = os_random() ^ now.sec ^ now.usec;
    244 	}
    245 	val %= 10000000;
    246 
    247 	/* Append checksum digit */
    248 	return val * 10 + wps_pin_checksum(val);
    249 }
    250 
    251 
    252 void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg,
    253 		    u16 config_error, u16 error_indication)
    254 {
    255 	union wps_event_data data;
    256 
    257 	if (wps->event_cb == NULL)
    258 		return;
    259 
    260 	os_memset(&data, 0, sizeof(data));
    261 	data.fail.msg = msg;
    262 	data.fail.config_error = config_error;
    263 	data.fail.error_indication = error_indication;
    264 	wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data);
    265 }
    266 
    267 
    268 void wps_success_event(struct wps_context *wps)
    269 {
    270 	if (wps->event_cb == NULL)
    271 		return;
    272 
    273 	wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, NULL);
    274 }
    275 
    276 
    277 void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part)
    278 {
    279 	union wps_event_data data;
    280 
    281 	if (wps->event_cb == NULL)
    282 		return;
    283 
    284 	os_memset(&data, 0, sizeof(data));
    285 	data.pwd_auth_fail.enrollee = enrollee;
    286 	data.pwd_auth_fail.part = part;
    287 	wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, &data);
    288 }
    289 
    290 
    291 void wps_pbc_overlap_event(struct wps_context *wps)
    292 {
    293 	if (wps->event_cb == NULL)
    294 		return;
    295 
    296 	wps->event_cb(wps->cb_ctx, WPS_EV_PBC_OVERLAP, NULL);
    297 }
    298 
    299 
    300 void wps_pbc_timeout_event(struct wps_context *wps)
    301 {
    302 	if (wps->event_cb == NULL)
    303 		return;
    304 
    305 	wps->event_cb(wps->cb_ctx, WPS_EV_PBC_TIMEOUT, NULL);
    306 }
    307 
    308 
    309 #ifdef CONFIG_WPS_OOB
    310 
    311 static struct wpabuf * wps_get_oob_cred(struct wps_context *wps)
    312 {
    313 	struct wps_data data;
    314 	struct wpabuf *plain;
    315 
    316 	plain = wpabuf_alloc(500);
    317 	if (plain == NULL) {
    318 		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
    319 			   "credential");
    320 		return NULL;
    321 	}
    322 
    323 	os_memset(&data, 0, sizeof(data));
    324 	data.wps = wps;
    325 	data.auth_type = wps->auth_types;
    326 	data.encr_type = wps->encr_types;
    327 	if (wps_build_version(plain) ||
    328 	    wps_build_cred(&data, plain) ||
    329 	    wps_build_wfa_ext(plain, 0, NULL, 0)) {
    330 		wpabuf_free(plain);
    331 		return NULL;
    332 	}
    333 
    334 	return plain;
    335 }
    336 
    337 
    338 static struct wpabuf * wps_get_oob_dev_pwd(struct wps_context *wps)
    339 {
    340 	struct wpabuf *data;
    341 
    342 	data = wpabuf_alloc(9 + WPS_OOB_DEVICE_PASSWORD_ATTR_LEN);
    343 	if (data == NULL) {
    344 		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
    345 			   "device password attribute");
    346 		return NULL;
    347 	}
    348 
    349 	wpabuf_free(wps->oob_conf.dev_password);
    350 	wps->oob_conf.dev_password =
    351 		wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1);
    352 	if (wps->oob_conf.dev_password == NULL) {
    353 		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
    354 			   "device password");
    355 		wpabuf_free(data);
    356 		return NULL;
    357 	}
    358 
    359 	if (wps_build_version(data) ||
    360 	    wps_build_oob_dev_password(data, wps) ||
    361 	    wps_build_wfa_ext(data, 0, NULL, 0)) {
    362 		wpa_printf(MSG_ERROR, "WPS: Build OOB device password "
    363 			   "attribute error");
    364 		wpabuf_free(data);
    365 		return NULL;
    366 	}
    367 
    368 	return data;
    369 }
    370 
    371 
    372 static int wps_parse_oob_dev_pwd(struct wps_context *wps,
    373 				 struct wpabuf *data)
    374 {
    375 	struct oob_conf_data *oob_conf = &wps->oob_conf;
    376 	struct wps_parse_attr attr;
    377 	const u8 *pos;
    378 
    379 	if (wps_parse_msg(data, &attr) < 0 ||
    380 	    attr.oob_dev_password == NULL) {
    381 		wpa_printf(MSG_ERROR, "WPS: OOB device password not found");
    382 		return -1;
    383 	}
    384 
    385 	pos = attr.oob_dev_password;
    386 
    387 	oob_conf->pubkey_hash =
    388 		wpabuf_alloc_copy(pos, WPS_OOB_PUBKEY_HASH_LEN);
    389 	if (oob_conf->pubkey_hash == NULL) {
    390 		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
    391 			   "public key hash");
    392 		return -1;
    393 	}
    394 	pos += WPS_OOB_PUBKEY_HASH_LEN;
    395 
    396 	wps->oob_dev_pw_id = WPA_GET_BE16(pos);
    397 	pos += sizeof(wps->oob_dev_pw_id);
    398 
    399 	oob_conf->dev_password =
    400 		wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1);
    401 	if (oob_conf->dev_password == NULL) {
    402 		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
    403 			   "device password");
    404 		return -1;
    405 	}
    406 	wpa_snprintf_hex_uppercase(wpabuf_put(oob_conf->dev_password,
    407 				   wpabuf_size(oob_conf->dev_password)),
    408 				   wpabuf_size(oob_conf->dev_password), pos,
    409 				   WPS_OOB_DEVICE_PASSWORD_LEN);
    410 
    411 	return 0;
    412 }
    413 
    414 
    415 static int wps_parse_oob_cred(struct wps_context *wps, struct wpabuf *data)
    416 {
    417 	struct wpabuf msg;
    418 	struct wps_parse_attr attr;
    419 	size_t i;
    420 
    421 	if (wps_parse_msg(data, &attr) < 0 || attr.num_cred <= 0) {
    422 		wpa_printf(MSG_ERROR, "WPS: OOB credential not found");
    423 		return -1;
    424 	}
    425 
    426 	for (i = 0; i < attr.num_cred; i++) {
    427 		struct wps_credential local_cred;
    428 		struct wps_parse_attr cattr;
    429 
    430 		os_memset(&local_cred, 0, sizeof(local_cred));
    431 		wpabuf_set(&msg, attr.cred[i], attr.cred_len[i]);
    432 		if (wps_parse_msg(&msg, &cattr) < 0 ||
    433 		    wps_process_cred(&cattr, &local_cred)) {
    434 			wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB "
    435 				   "credential");
    436 			return -1;
    437 		}
    438 		wps->cred_cb(wps->cb_ctx, &local_cred);
    439 	}
    440 
    441 	return 0;
    442 }
    443 
    444 
    445 int wps_process_oob(struct wps_context *wps, struct oob_device_data *oob_dev,
    446 		    int registrar)
    447 {
    448 	struct wpabuf *data;
    449 	int ret, write_f, oob_method = wps->oob_conf.oob_method;
    450 	void *oob_priv;
    451 
    452 	write_f = oob_method == OOB_METHOD_DEV_PWD_E ? !registrar : registrar;
    453 
    454 	oob_priv = oob_dev->init_func(wps, oob_dev, registrar);
    455 	if (oob_priv == NULL) {
    456 		wpa_printf(MSG_ERROR, "WPS: Failed to initialize OOB device");
    457 		return -1;
    458 	}
    459 
    460 	if (write_f) {
    461 		if (oob_method == OOB_METHOD_CRED)
    462 			data = wps_get_oob_cred(wps);
    463 		else
    464 			data = wps_get_oob_dev_pwd(wps);
    465 
    466 		ret = 0;
    467 		if (data == NULL || oob_dev->write_func(oob_priv, data) < 0)
    468 			ret = -1;
    469 	} else {
    470 		data = oob_dev->read_func(oob_priv);
    471 		if (data == NULL)
    472 			ret = -1;
    473 		else {
    474 			if (oob_method == OOB_METHOD_CRED)
    475 				ret = wps_parse_oob_cred(wps, data);
    476 			else
    477 				ret = wps_parse_oob_dev_pwd(wps, data);
    478 		}
    479 	}
    480 	wpabuf_free(data);
    481 	oob_dev->deinit_func(oob_priv);
    482 
    483 	if (ret < 0) {
    484 		wpa_printf(MSG_ERROR, "WPS: Failed to process OOB data");
    485 		return -1;
    486 	}
    487 
    488 	return 0;
    489 }
    490 
    491 
    492 struct oob_device_data * wps_get_oob_device(char *device_type)
    493 {
    494 #ifdef CONFIG_WPS_UFD
    495 	if (os_strstr(device_type, "ufd") != NULL)
    496 		return &oob_ufd_device_data;
    497 #endif /* CONFIG_WPS_UFD */
    498 #ifdef CONFIG_WPS_NFC
    499 	if (os_strstr(device_type, "nfc") != NULL)
    500 		return &oob_nfc_device_data;
    501 #endif /* CONFIG_WPS_NFC */
    502 
    503 	return NULL;
    504 }
    505 
    506 
    507 #ifdef CONFIG_WPS_NFC
    508 struct oob_nfc_device_data * wps_get_oob_nfc_device(char *device_name)
    509 {
    510 	if (device_name == NULL)
    511 		return NULL;
    512 #ifdef CONFIG_WPS_NFC_PN531
    513 	if (os_strstr(device_name, "pn531") != NULL)
    514 		return &oob_nfc_pn531_device_data;
    515 #endif /* CONFIG_WPS_NFC_PN531 */
    516 
    517 	return NULL;
    518 }
    519 #endif /* CONFIG_WPS_NFC */
    520 
    521 
    522 int wps_get_oob_method(char *method)
    523 {
    524 	if (os_strstr(method, "pin-e") != NULL)
    525 		return OOB_METHOD_DEV_PWD_E;
    526 	if (os_strstr(method, "pin-r") != NULL)
    527 		return OOB_METHOD_DEV_PWD_R;
    528 	if (os_strstr(method, "cred") != NULL)
    529 		return OOB_METHOD_CRED;
    530 	return OOB_METHOD_UNKNOWN;
    531 }
    532 
    533 #endif /* CONFIG_WPS_OOB */
    534 
    535 
    536 int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN])
    537 {
    538 	const char *pos;
    539 
    540 	/* <categ>-<OUI>-<subcateg> */
    541 	WPA_PUT_BE16(dev_type, atoi(str));
    542 	pos = os_strchr(str, '-');
    543 	if (pos == NULL)
    544 		return -1;
    545 	pos++;
    546 	if (hexstr2bin(pos, &dev_type[2], 4))
    547 		return -1;
    548 	pos = os_strchr(pos, '-');
    549 	if (pos == NULL)
    550 		return -1;
    551 	pos++;
    552 	WPA_PUT_BE16(&dev_type[6], atoi(pos));
    553 
    554 
    555 	return 0;
    556 }
    557 
    558 
    559 char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf,
    560 			    size_t buf_len)
    561 {
    562 	int ret;
    563 
    564 	ret = os_snprintf(buf, buf_len, "%u-%08X-%u",
    565 			  WPA_GET_BE16(dev_type), WPA_GET_BE32(&dev_type[2]),
    566 			  WPA_GET_BE16(&dev_type[6]));
    567 	if (ret < 0 || (unsigned int) ret >= buf_len)
    568 		return NULL;
    569 
    570 	return buf;
    571 }
    572 
    573 
    574 void uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid)
    575 {
    576 	const u8 *addr[2];
    577 	size_t len[2];
    578 	u8 hash[SHA1_MAC_LEN];
    579 	u8 nsid[16] = {
    580 		0x52, 0x64, 0x80, 0xf8,
    581 		0xc9, 0x9b,
    582 		0x4b, 0xe5,
    583 		0xa6, 0x55,
    584 		0x58, 0xed, 0x5f, 0x5d, 0x60, 0x84
    585 	};
    586 
    587 	addr[0] = nsid;
    588 	len[0] = sizeof(nsid);
    589 	addr[1] = mac_addr;
    590 	len[1] = 6;
    591 	sha1_vector(2, addr, len, hash);
    592 	os_memcpy(uuid, hash, 16);
    593 
    594 	/* Version: 5 = named-based version using SHA-1 */
    595 	uuid[6] = (5 << 4) | (uuid[6] & 0x0f);
    596 
    597 	/* Variant specified in RFC 4122 */
    598 	uuid[8] = 0x80 | (uuid[8] & 0x3f);
    599 }
    600 
    601 
    602 u16 wps_config_methods_str2bin(const char *str)
    603 {
    604 	u16 methods = 0;
    605 
    606 	if (str == NULL) {
    607 		/* Default to enabling methods based on build configuration */
    608 		methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
    609 #ifdef CONFIG_WPS2
    610 		methods |= WPS_CONFIG_VIRT_DISPLAY;
    611 #endif /* CONFIG_WPS2 */
    612 #ifdef CONFIG_WPS_UFD
    613 		methods |= WPS_CONFIG_USBA;
    614 #endif /* CONFIG_WPS_UFD */
    615 #ifdef CONFIG_WPS_NFC
    616 		methods |= WPS_CONFIG_NFC_INTERFACE;
    617 #endif /* CONFIG_WPS_NFC */
    618 	} else {
    619 		if (os_strstr(str, "usba"))
    620 			methods |= WPS_CONFIG_USBA;
    621 		if (os_strstr(str, "ethernet"))
    622 			methods |= WPS_CONFIG_ETHERNET;
    623 		if (os_strstr(str, "label"))
    624 			methods |= WPS_CONFIG_LABEL;
    625 		if (os_strstr(str, "display"))
    626 			methods |= WPS_CONFIG_DISPLAY;
    627 		if (os_strstr(str, "ext_nfc_token"))
    628 			methods |= WPS_CONFIG_EXT_NFC_TOKEN;
    629 		if (os_strstr(str, "int_nfc_token"))
    630 			methods |= WPS_CONFIG_INT_NFC_TOKEN;
    631 		if (os_strstr(str, "nfc_interface"))
    632 			methods |= WPS_CONFIG_NFC_INTERFACE;
    633 		if (os_strstr(str, "push_button"))
    634 			methods |= WPS_CONFIG_PUSHBUTTON;
    635 		if (os_strstr(str, "keypad"))
    636 			methods |= WPS_CONFIG_KEYPAD;
    637 #ifdef CONFIG_WPS2
    638 		if (os_strstr(str, "virtual_display"))
    639 			methods |= WPS_CONFIG_VIRT_DISPLAY;
    640 		if (os_strstr(str, "physical_display"))
    641 			methods |= WPS_CONFIG_PHY_DISPLAY;
    642 		if (os_strstr(str, "virtual_push_button"))
    643 			methods |= WPS_CONFIG_VIRT_PUSHBUTTON;
    644 		if (os_strstr(str, "physical_push_button"))
    645 			methods |= WPS_CONFIG_PHY_PUSHBUTTON;
    646 #endif /* CONFIG_WPS2 */
    647 	}
    648 
    649 	return methods;
    650 }
    651 
    652 
    653 struct wpabuf * wps_build_wsc_ack(struct wps_data *wps)
    654 {
    655 	struct wpabuf *msg;
    656 
    657 	wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK");
    658 
    659 	msg = wpabuf_alloc(1000);
    660 	if (msg == NULL)
    661 		return NULL;
    662 
    663 	if (wps_build_version(msg) ||
    664 	    wps_build_msg_type(msg, WPS_WSC_ACK) ||
    665 	    wps_build_enrollee_nonce(wps, msg) ||
    666 	    wps_build_registrar_nonce(wps, msg) ||
    667 	    wps_build_wfa_ext(msg, 0, NULL, 0)) {
    668 		wpabuf_free(msg);
    669 		return NULL;
    670 	}
    671 
    672 	return msg;
    673 }
    674 
    675 
    676 struct wpabuf * wps_build_wsc_nack(struct wps_data *wps)
    677 {
    678 	struct wpabuf *msg;
    679 
    680 	wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK");
    681 
    682 	msg = wpabuf_alloc(1000);
    683 	if (msg == NULL)
    684 		return NULL;
    685 
    686 	if (wps_build_version(msg) ||
    687 	    wps_build_msg_type(msg, WPS_WSC_NACK) ||
    688 	    wps_build_enrollee_nonce(wps, msg) ||
    689 	    wps_build_registrar_nonce(wps, msg) ||
    690 	    wps_build_config_error(msg, wps->config_error) ||
    691 	    wps_build_wfa_ext(msg, 0, NULL, 0)) {
    692 		wpabuf_free(msg);
    693 		return NULL;
    694 	}
    695 
    696 	return msg;
    697 }
    698