int wps_build_oob_dev_password(struct wpabuf *msg, struct wps_context *wps)
{
	u8 dev_password_bin[WPS_OOB_DEVICE_PASSWORD_LEN];

	wpa_printf(MSG_DEBUG, "WPS:  * OOB Device Password");

	if (os_get_random((u8 *) &wps->oob_dev_pw_id, sizeof(u16)) < 0) {
		wpa_printf(MSG_ERROR, "WPS: device password id "
			   "generation error");
		return -1;
	}
	wps->oob_dev_pw_id |= 0x0010;

	if (random_get_bytes(dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN) <
	    0) {
		wpa_printf(MSG_ERROR, "WPS: OOB device password "
			   "generation error");
		return -1;
	}

	wpa_snprintf_hex_uppercase(
		wpabuf_put(wps->oob_conf.dev_password,
			   wpabuf_size(wps->oob_conf.dev_password)),
		wpabuf_size(wps->oob_conf.dev_password),
		dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN);

	return wps_build_oob_dev_pw(msg, wps->oob_dev_pw_id, wps->dh_pubkey,
				    dev_password_bin,
				    WPS_OOB_DEVICE_PASSWORD_LEN);
}
int main(int argc, char *argv[])
{
	struct wpa_supplicant wpa_s;
	int ret = -1;
	struct wpabuf *buf = NULL, *ndef = NULL;
	char txt[1000];

	if (os_program_init())
		return -1;
	random_init(NULL);

	os_memset(&wpa_s, 0, sizeof(wpa_s));
	wpa_s.conf = os_zalloc(sizeof(*wpa_s.conf));
	if (wpa_s.conf == NULL)
		goto fail;

	buf = wpas_wps_nfc_token(&wpa_s, 0);
	if (buf == NULL)
		goto fail;

	ndef = ndef_build_wifi(buf);
	if (ndef == NULL)
		goto fail;

	wpa_snprintf_hex_uppercase(txt, sizeof(txt), wpabuf_head(buf),
				   wpabuf_len(buf));
	printf("#WPS=%s\n", txt);

	wpa_snprintf_hex_uppercase(txt, sizeof(txt), wpabuf_head(ndef),
				   wpabuf_len(ndef));
	printf("#NDEF=%s\n", txt);

	printf("wps_nfc_dev_pw_id=%d\n", wpa_s.conf->wps_nfc_dev_pw_id);
	print_bin("wps_nfc_dh_pubkey", wpa_s.conf->wps_nfc_dh_pubkey);
	print_bin("wps_nfc_dh_privkey", wpa_s.conf->wps_nfc_dh_privkey);
	print_bin("wps_nfc_dev_pw", wpa_s.conf->wps_nfc_dev_pw);

	ret = 0;
fail:
	wpabuf_free(ndef);
	wpabuf_free(buf);
	wpa_config_free(wpa_s.conf);
	random_deinit();
	os_program_deinit();

	return ret;
}
示例#3
0
static u8 * eap_mschapv2_build_success_req(struct eap_sm *sm,
					   struct eap_mschapv2_data *data,
					   int id, size_t *reqDataLen)
{
	struct eap_hdr *req;
	struct eap_mschapv2_hdr *ms;
	u8 *pos, *msg;
	char *message = "OK";
	size_t ms_len;

	ms_len = sizeof(*ms) + 2 + 2 * sizeof(data->auth_response) + 1 + 2 +
		strlen(message);
	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, reqDataLen,
			    ms_len, EAP_CODE_REQUEST, id, &pos);
	if (req == NULL) {
		wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory"
			   " for request");
		data->state = FAILURE;
		return NULL;
	}

	ms = (struct eap_mschapv2_hdr *) pos;
	ms->op_code = MSCHAPV2_OP_SUCCESS;
	ms->mschapv2_id = data->resp_mschapv2_id;
	WPA_PUT_BE16(ms->ms_length, ms_len);

	msg = pos = (u8 *) (ms + 1);
	*pos++ = 'S';
	*pos++ = '=';
	pos += wpa_snprintf_hex_uppercase((char *) pos,
					  sizeof(data->auth_response) * 2 + 1,
					  data->auth_response,
					  sizeof(data->auth_response));
	*pos++ = ' ';
	*pos++ = 'M';
	*pos++ = '=';
	memcpy(pos, message, strlen(message));

	wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Success Request Message",
			  msg, ms_len - sizeof(*ms));

	return (u8 *) req;
}
static struct wpabuf * eap_mschapv2_build_success_req(
	struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id)
{
	struct wpabuf *req;
	struct eap_mschapv2_hdr *ms;
	u8 *msg;
	char *message = "OK";
	size_t ms_len;

	ms_len = sizeof(*ms) + 2 + 2 * sizeof(data->auth_response) + 1 + 2 +
		os_strlen(message);
	req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
			    EAP_CODE_REQUEST, id);
	if (req == NULL) {
		wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory"
			   " for request");
		data->state = FAILURE;
		return NULL;
	}

	ms = wpabuf_put(req, sizeof(*ms));
	ms->op_code = MSCHAPV2_OP_SUCCESS;
	ms->mschapv2_id = data->resp_mschapv2_id;
	WPA_PUT_BE16(ms->ms_length, ms_len);
	msg = (u8 *) (ms + 1);

	wpabuf_put_u8(req, 'S');
	wpabuf_put_u8(req, '=');
	wpa_snprintf_hex_uppercase(
		wpabuf_put(req, sizeof(data->auth_response) * 2),
		sizeof(data->auth_response) * 2 + 1,
		data->auth_response, sizeof(data->auth_response));
	wpabuf_put_u8(req, ' ');
	wpabuf_put_u8(req, 'M');
	wpabuf_put_u8(req, '=');
	wpabuf_put_data(req, message, os_strlen(message));

	wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Success Request Message",
			  msg, ms_len - sizeof(*ms));

	return req;
}
示例#5
0
static int wps_parse_oob_dev_pwd(struct wps_context *wps,
				 struct wpabuf *data)
{
	struct oob_conf_data *oob_conf = &wps->oob_conf;
	struct wps_parse_attr attr;
	const u8 *pos;

	if (wps_parse_msg(data, &attr) < 0 ||
	    attr.oob_dev_password == NULL) {
		wpa_printf(MSG_ERROR, "WPS: OOB device password not found");
		return -1;
	}

	pos = attr.oob_dev_password;

	oob_conf->pubkey_hash =
		wpabuf_alloc_copy(pos, WPS_OOB_PUBKEY_HASH_LEN);
	if (oob_conf->pubkey_hash == NULL) {
		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
			   "public key hash");
		return -1;
	}
	pos += WPS_OOB_PUBKEY_HASH_LEN;

	wps->oob_dev_pw_id = WPA_GET_BE16(pos);
	pos += sizeof(wps->oob_dev_pw_id);

	oob_conf->dev_password =
		wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1);
	if (oob_conf->dev_password == NULL) {
		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
			   "device password");
		return -1;
	}
	wpa_snprintf_hex_uppercase(wpabuf_put(oob_conf->dev_password,
				   wpabuf_size(oob_conf->dev_password)),
				   wpabuf_size(oob_conf->dev_password), pos,
				   WPS_OOB_DEVICE_PASSWORD_LEN);

	return 0;
}
int wps_build_oob_dev_password(struct wpabuf *msg, struct wps_context *wps)
{
	size_t hash_len;
	const u8 *addr[1];
	u8 pubkey_hash[WPS_HASH_LEN];
	u8 dev_password_bin[WPS_OOB_DEVICE_PASSWORD_LEN];

	wpa_printf(MSG_DEBUG, "WPS:  * OOB Device Password");

	addr[0] = wpabuf_head(wps->dh_pubkey);
	hash_len = wpabuf_len(wps->dh_pubkey);
	sha256_vector(1, addr, &hash_len, pubkey_hash);

	if (os_get_random((u8 *) &wps->oob_dev_pw_id, sizeof(u16)) < 0) {
		wpa_printf(MSG_ERROR, "WPS: device password id "
			   "generation error");
		return -1;
	}
	wps->oob_dev_pw_id |= 0x0010;

	if (random_get_bytes(dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN) <
	    0) {
		wpa_printf(MSG_ERROR, "WPS: OOB device password "
			   "generation error");
		return -1;
	}

	wpabuf_put_be16(msg, ATTR_OOB_DEVICE_PASSWORD);
	wpabuf_put_be16(msg, WPS_OOB_DEVICE_PASSWORD_ATTR_LEN);
	wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
	wpabuf_put_be16(msg, wps->oob_dev_pw_id);
	wpabuf_put_data(msg, dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN);

	wpa_snprintf_hex_uppercase(
		wpabuf_put(wps->oob_conf.dev_password,
			   wpabuf_size(wps->oob_conf.dev_password)),
		wpabuf_size(wps->oob_conf.dev_password),
		dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN);

	return 0;
}
示例#7
0
int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd)
{
	struct wps_context *wps = hapd->wps;
	struct wpabuf *pw;

	if (wps == NULL)
		return -1;

	if (!hapd->conf->wps_nfc_dh_pubkey ||
	    !hapd->conf->wps_nfc_dh_privkey ||
	    !hapd->conf->wps_nfc_dev_pw ||
	    !hapd->conf->wps_nfc_dev_pw_id)
		return -1;

	hostapd_wps_nfc_clear(wps);
	wpa_printf(MSG_DEBUG,
		   "WPS: Enable NFC Tag (Dev Pw Id %u) for AP interface %s (context %p)",
		   hapd->conf->wps_nfc_dev_pw_id, hapd->conf->iface, wps);
	wps->ap_nfc_dev_pw_id = hapd->conf->wps_nfc_dev_pw_id;
	wps->ap_nfc_dh_pubkey = wpabuf_dup(hapd->conf->wps_nfc_dh_pubkey);
	wps->ap_nfc_dh_privkey = wpabuf_dup(hapd->conf->wps_nfc_dh_privkey);
	pw = hapd->conf->wps_nfc_dev_pw;
	wps->ap_nfc_dev_pw = wpabuf_alloc(
		wpabuf_len(pw) * 2 + 1);
	if (wps->ap_nfc_dev_pw) {
		wpa_snprintf_hex_uppercase(
			(char *) wpabuf_put(wps->ap_nfc_dev_pw,
					    wpabuf_len(pw) * 2),
			wpabuf_len(pw) * 2 + 1,
			wpabuf_head(pw), wpabuf_len(pw));
	}

	if (!wps->ap_nfc_dh_pubkey || !wps->ap_nfc_dh_privkey ||
	    !wps->ap_nfc_dev_pw) {
		hostapd_wps_nfc_clear(wps);
		return -1;
	}

	return 0;
}
示例#8
0
int wps_get_supplicant_ssid_configuration(void *ctx, int index, u8 **buf, size_t *len)
{
	int ret = -1;
	struct wpa_supplicant *wpa_s = ctx;
	struct wpa_ssid *ssid;
	struct wps_data *wps = 0;
	u16 auth, encr;
	Boolean enabled8021x = 0;
	u8 nwKeyIdx = -1;
	u8 nwKey[64 + 1];
	Boolean blval;
	size_t length;
	u8 nwIdx;

	do {
		if (!buf || !len)
			break;
		*buf = 0;
		*len = 0;

		ssid = wpa_config_get_network(wpa_s->conf, index);
		if (!ssid)
			break;

		if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
			if (ssid->proto & WPA_PROTO_RSN)
				auth = WPS_AUTHTYPE_WPA2;
			else
				auth = WPS_AUTHTYPE_WPA;

			if (ssid->pairwise_cipher & WPA_CIPHER_CCMP)
				encr = WPS_ENCRTYPE_AES;
			else
				encr = WPS_ENCRTYPE_TKIP;
			enabled8021x = 1;
		} else if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
			if (ssid->proto & WPA_PROTO_RSN)
				auth = WPS_AUTHTYPE_WPA2PSK;
			else
				auth = WPS_AUTHTYPE_WPAPSK;

			if (ssid->pairwise_cipher & WPA_CIPHER_CCMP)
				encr = WPS_ENCRTYPE_AES;
			else
				encr = WPS_ENCRTYPE_TKIP;
			nwKeyIdx = 0;
		} else if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) {
			if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
				auth = WPS_AUTHTYPE_SHARED;
				nwKeyIdx = ssid->wep_tx_keyidx + 1;
			} else
				auth = WPS_AUTHTYPE_OPEN;

			if ((ssid->pairwise_cipher & (WPA_CIPHER_WEP40|WPA_CIPHER_WEP104)) ||
				(ssid->group_cipher & (WPA_CIPHER_WEP40|WPA_CIPHER_WEP104))) {
				encr = WPS_ENCRTYPE_WEP;
				nwKeyIdx = ssid->wep_tx_keyidx + 1;
			} else
				encr = WPS_ENCRTYPE_NONE;
		} else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
			auth = WPS_AUTHTYPE_OPEN;
			encr = WPS_ENCRTYPE_WEP;
			enabled8021x = 1;
		}

		if (wps_create_wps_data(&wps))
			break;

		/* Network Index */
		nwIdx = ssid->id;
		if (wps_set_value(wps, WPS_TYPE_NW_INDEX, &nwIdx, 0))
			break;

		/* SSID */
		if (wps_set_value(wps, WPS_TYPE_SSID, ssid->ssid, ssid->ssid_len))
			break;

		/* Authentication Type */
		if (wps_set_value(wps, WPS_TYPE_AUTH_TYPE, &auth, 0))
			break;

		/* Encryption Type */
		if (wps_set_value(wps, WPS_TYPE_ENCR_TYPE, &encr, 0))
			break;

		if (nwKeyIdx != (u8)-1) {
			if (encr == WPS_ENCRTYPE_WEP) {
				if ((1 > nwKeyIdx) || (4 < nwKeyIdx)) {
					wpa_printf(MSG_WARNING, "Network Key Index is fixed. %d -> 1\n", nwKeyIdx);
					nwKeyIdx = 1;
				}

				/* Network Key Index (Option) */
				if (wps_set_value(wps, WPS_TYPE_NW_KEY_INDEX, &nwKeyIdx, 0))
					break;
			}

			/* Network Key */
			if (ssid->passphrase) {
				length = os_strlen(ssid->passphrase);
				strncpy((char *)nwKey, ssid->passphrase, length);
				nwKey[length] = 0;
			} else if (ssid->psk_set) {
				length = PMK_LEN * 2;
				wpa_snprintf_hex_uppercase((char *)nwKey, sizeof(nwKey), ssid->psk, length);
				nwKey[length] = 0;
			} else {
				if (is_hex(ssid->wep_key[nwKeyIdx - 1], ssid->wep_key_len[nwKeyIdx - 1])) {
					length = (u16)ssid->wep_key_len[nwKeyIdx - 1] * 2;
					wpa_snprintf_hex_uppercase((char *)nwKey, sizeof(nwKey), ssid->wep_key[nwKeyIdx - 1], length);
					nwKey[length] = 0;
				} else {
					length = (u16)ssid->wep_key_len[nwKeyIdx - 1];
					strncpy((char *)nwKey, (char *)ssid->wep_key[nwKeyIdx - 1], length);
					nwKey[length] = 0;
				}
			}
			if (wps_set_value(wps, WPS_TYPE_NW_KEY, nwKey, length))
				break;
		} else {
			/* Network Key (No Key) */
			if (wps_set_value(wps, WPS_TYPE_NW_KEY, 0, 0)) {
				break;
			}
		}

		/* MAC Address */
		if (wps_set_value(wps, WPS_TYPE_MAC_ADDR, wpa_s->own_addr, ETH_ALEN))
			break;

		if (enabled8021x) {
			char *value;

			/* EAP Type (Option) */
			value = wpa_config_get(ssid, "eap");
			if (value) {
				if (wps_set_value(wps, WPS_TYPE_EAP_TYPE, value, os_strlen(value))) {
					free(value);
					break;
				}
				free(value);
			}

			/* EAP Identity (Option) */
			value = wpa_config_get(ssid, "identity");
			if (value) {
				if (wps_set_value(wps, WPS_TYPE_EAP_IDENTITY, value, os_strlen(value))) {
					free(value);
					break;
				}
				free(value);
			}

			/* Key Provided Automaticaly (Option) */
			blval = 1;
			if (wps_set_value(wps, WPS_TYPE_KEY_PROVIDED_AUTO, &blval, 0))
				break;

			/* 802.1X Enabled (Option) */
			if (wps_set_value(wps, WPS_TYPE_8021X_ENABLED, &enabled8021x, 0))
				break;
		}

		if (wps_write_wps_data(wps, buf, len))
			break;

		ret = 0;
	} while (0);

	(void)wps_destroy_wps_data(&wps);

	if (ret) {
		if (buf && *buf) {
			free(*buf);
			*buf = 0;
		}
		if (len)
			*len = 0;
	}

	return ret;
}
示例#9
0
/*
 * This installs received WPS configuration into a new network configuration.
 * It is optional that the new network configuration be saved to the
 * original configuration file.
 */
int wps_set_supplicant_ssid_configuration(void *ctx, u8 *buf, size_t len)
{
	int ret = -1;
	struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)ctx;
	struct wpa_ssid *ssid = 0;
	struct wps_data *wps = 0;
	u8 str_ssid[33];
	size_t ssid_length;
	u16 auth, encr;
	u8 nwKeyIdx;
	u8 *nwKey = 0;
	size_t nwKey_length;
	u8 macAddr[6];
	char *eapType = 0;
	char *eapIdentity = 0;
	Boolean keyProvideAuto;
	Boolean enabled8021X;
	Boolean passphrase = 0;
	size_t length;
	char *var, *value;

	do {
		if (!wpa_s)
			break;

                /* Optionally share new configuration with other software,
                 * e.g. with hostapd.
                 */
                wps_new_configuration_share(wpa_s, buf, len);

		ssid = wpa_config_add_network(wpa_s->conf);
		if (!ssid)
			break;
		wpa_config_set_network_defaults(ssid);

		if (wps_create_wps_data(&wps))
			break;

		if(wps_parse_wps_data(buf, len, wps))
			break;

		/* SSID */
		ssid_length = sizeof(str_ssid);
		if(wps_get_value(wps, WPS_TYPE_SSID, str_ssid, &ssid_length))
			break;
		str_ssid[ssid_length] = 0;

		/* Authentication Type */
		if (wps_get_value(wps, WPS_TYPE_AUTH_TYPE, &auth, NULL))
			break;

		/* Encryption Type */
		if (wps_get_value(wps, WPS_TYPE_ENCR_TYPE, &encr, NULL))
			break;

		/* Network Key Index (Option) */
		if(wps_get_value(wps, WPS_TYPE_NW_KEY_INDEX, &nwKeyIdx, NULL))
			nwKeyIdx = 1;
		if ((1 > nwKeyIdx) || (4 < nwKeyIdx)) { /* warning */
			wpa_printf(MSG_WARNING, "Network Key Index is fixed. %d -> 1\n", nwKeyIdx);
			nwKeyIdx = 1;
		}

		/* Network Key */
		nwKey_length = 0;
		(void)wps_get_value(wps, WPS_TYPE_NW_KEY, NULL, &nwKey_length);
		if (nwKey_length) {
			nwKey = (u8 *)calloc(1, nwKey_length + 1);
			if (!nwKey)
				break;
			if (wps_get_value(wps, WPS_TYPE_NW_KEY, nwKey, &nwKey_length)) {
				break;
			}
			nwKey[nwKey_length] = 0;
		}

		/* MAC Address */
		length = sizeof(macAddr);
		if(wps_get_value(wps, WPS_TYPE_MAC_ADDR, macAddr, &length))
			break;

		/* EAP Type (Option) */
		length = 0;
		(void)wps_get_value(wps, WPS_TYPE_EAP_TYPE, NULL, &length);
		if (length) {
			eapType = (char *)calloc(1, length + 1);
			if (!eapType)
				break;
			if (wps_get_value(wps, WPS_TYPE_EAP_TYPE, eapType, &length)) {
				break;
			}
			eapType[length] = 0;
		}

		/* EAP Identity (Option) */
		length = 0;
		(void)wps_get_value(wps, WPS_TYPE_EAP_IDENTITY, NULL, &length);
		if (length) {
			eapIdentity = (char *)calloc(1, length + 1);
			if (!eapIdentity)
				break;
			if (wps_get_value(wps, WPS_TYPE_EAP_IDENTITY, eapIdentity, &length)) {
				break;
			}
			eapIdentity[length] = 0;
		}

		/* Key Provided Automaticaly (Option) */
		if(wps_get_value(wps, WPS_TYPE_KEY_PROVIDED_AUTO, &keyProvideAuto, NULL))
			keyProvideAuto = 0;

		/* 802.1X Enabled (Option) */
		if(wps_get_value(wps, WPS_TYPE_8021X_ENABLED, &enabled8021X, NULL))
			enabled8021X = 0;

		/* Set Configuration */
                /* %%%%%% Sony set disabled to 1... why? */
		ssid->disabled = 0;
		/* ssid */
		var = "ssid";
		value = (char *)os_malloc(os_strlen((char *)str_ssid) + 3);
		if (!value)
			break;
		os_snprintf(value, os_strlen((char *)str_ssid) + 3, "\"%s\"", str_ssid);
		if (wpa_config_set(ssid, var, value, 0))
			break;
		free(value);

		/* auth_alg */
		var = "auth_alg";
		if (WPS_AUTHTYPE_SHARED == auth)
			value = "SHARED";
		else
			value = "OPEN";
		if (wpa_config_set(ssid, var, value, 0))
			break;

		/* key_mgmt */
		var = "key_mgmt";
		switch (auth) {
		case WPS_AUTHTYPE_OPEN:
		case WPS_AUTHTYPE_SHARED:
			if (enabled8021X)
				value = "IEEE8021X";
			else
				value = "NONE";
			break;
		case WPS_AUTHTYPE_WPAPSK:
		case WPS_AUTHTYPE_WPA2PSK:
			if (enabled8021X)
				value = "WPA-PSK IEEE8021X";
			else
				value = "WPA-PSK";
			break;
		case WPS_AUTHTYPE_WPA:
		case WPS_AUTHTYPE_WPA2:
			if (enabled8021X)
				value = "WPA-EAP IEEE8021X";
			else
				value = "WPA-EAP";
			break;
		default:
			value = 0;
			break;
		}
		if (!value | wpa_config_set(ssid, var, value, 0))
			break;

		/* proto */
		var = "proto";
		switch (auth) {
		case WPS_AUTHTYPE_WPA:
		case WPS_AUTHTYPE_WPAPSK:
			value = "WPA";
			break;
		case WPS_AUTHTYPE_WPA2:
		case WPS_AUTHTYPE_WPA2PSK:
			value = "RSN";
			break;
		default:
			ssid->proto = 0;
			value = 0;
			break;
		}
		if (value && wpa_config_set(ssid, var, value, 0))
			break;

		/* pariwise */
		var = "pairwise";
		switch (encr) {
		case WPS_ENCRTYPE_NONE:
			ssid->pairwise_cipher = WPA_CIPHER_NONE;
			value = 0;
			break;
		case WPS_ENCRTYPE_TKIP:
			value = "TKIP";
			break;
		case WPS_ENCRTYPE_AES:
			value = "CCMP";
			break;
		default:
			value = 0;
			break;
		}
		if (value && wpa_config_set(ssid, var, value, 0))
			break;

		/* group */
		var = "group";
		switch (encr) {
		case WPS_ENCRTYPE_NONE:
			ssid->group_cipher = WPA_CIPHER_NONE;
			value = 0;
			break;
		case WPS_ENCRTYPE_WEP:
			value = "WEP104 WEP40";
			break;
		case WPS_ENCRTYPE_TKIP:
			value = "TKIP";
			break;
		case WPS_ENCRTYPE_AES:
                        #if 0   /* original */
			value = "CCMP";
                        #else   /* HACK! */
                        /* It is not uncommon for group cipher to be
                         * TKIP whereas the pairwise is CCMP, but 
                         * WPS makes no distinction.
                         * Workaround by configuring both in this case.
                         */
			value = "TKIP CCMP";
                        #endif
			break;
		default:
			value = 0;
			break;
		}
		if (value && wpa_config_set(ssid, var, value, 0))
			break;

		/* wep_tx_keyidx */
		var = "wep_tx_keyidx";
		switch (encr) {
		case WPS_ENCRTYPE_WEP:
			value = (char *)os_malloc(2);
			if (!value)
				break;
			os_snprintf(value, 2, "%d", nwKeyIdx - 1);
			break;
		default:
			value = 0;
			break;
		}
		if (value && wpa_config_set(ssid, var, value, 0)) {
			free(value);
			break;
		} else if (value)
			free(value);
		if (!value && (WPS_ENCRTYPE_WEP == encr))
			break;

		/* wep_keyn */
		switch (encr) {
		case WPS_ENCRTYPE_WEP:
			var = (char *)os_malloc(9);
			if (!var)
				break;
			os_snprintf(var, 9, "wep_key%d", nwKeyIdx - 1);
			if (is_hex(nwKey, nwKey_length)) {
				value = (char *)os_malloc(nwKey_length * 2 + 1);
				if (!value)
					break;
				wpa_snprintf_hex_uppercase(value, nwKey_length * 2 + 1,
										   nwKey, nwKey_length);
				value[nwKey_length * 2] = 0;
			} else if ((5 == nwKey_length) || (13 == nwKey_length)) {
				value = (char *)os_malloc(nwKey_length + 3);
				if (!value)
					break;
				os_snprintf(value, nwKey_length + 3, "\"%s\"", nwKey);
			} else if ((nwKey_length) || (13 == nwKey_length)) {
				value = (char *)os_malloc(nwKey_length + 1);
				if (!value)
					break;
				os_memcpy(value, nwKey, nwKey_length);
				value[nwKey_length] = 0;
			}
			break;
		default:
			var = 0;
			value = 0;
			break;
		}
		if (var && value && wpa_config_set(ssid, var, value, 0))
			break;
		if (var)
			free(var);
		if (value)
			free(value);
		if ((!var || !value) && (WPS_ENCRTYPE_WEP == encr))
			break;

		/* psk */
		var = "psk";
		switch (auth) {
		case WPS_AUTHTYPE_WPA:
		case WPS_AUTHTYPE_WPA2:
		case WPS_AUTHTYPE_WPAPSK:
		case WPS_AUTHTYPE_WPA2PSK:
			if (nwKey_length) {
				value = (char *)os_malloc(nwKey_length + 3);
				if (!value)
					break;
				if (64 > nwKey_length) {
					os_snprintf(value, nwKey_length + 3, "\"%s\"", nwKey);
					passphrase = 1;
				} else if (64 == nwKey_length) {
					os_memcpy(value, nwKey, nwKey_length);
					value[nwKey_length] = 0;
				} else {
					free(value);
					value = 0;
					break;
				}
			} else
				value = 0;
			break;
		default:
			value = 0;
			break;
		}
		if (value && wpa_config_set(ssid, var, value, 0)) {
			free(value);
			break;
		} else if (value)
			free(value);
		if (nwKey_length && !value &&
			((WPS_AUTHTYPE_WPA == auth) ||
			 (WPS_AUTHTYPE_WPA2 == auth) ||
			 (WPS_AUTHTYPE_WPAPSK == auth) ||
			 (WPS_AUTHTYPE_WPA2PSK == auth)))
			break;
		
		/* eap */
		if (eapType && os_strlen(eapType)) {
			var = "eap";
			value = (char *)eapType;
			if (wpa_config_set(ssid, var, value, 0))
				break;
		}

		/* identity */
		if (eapIdentity && os_strlen(eapIdentity)) {
			var = "identity";
			value = (char *)eapIdentity;
			if (wpa_config_set(ssid, var, value, 0))
				break;
		}

		ret = 0;
	} while (0);

	(void)wps_destroy_wps_data(&wps);

	if (ret) {
		if (ssid)
			(void)wpa_config_remove_network(wpa_s->conf, ssid->id);
	} else {
		if (passphrase)
			wpa_config_update_psk(ssid);
	}

	if (nwKey)
		free(nwKey);
	if (eapType)
		free(eapType);
	if (eapIdentity)
		free(eapIdentity);

	return ret?ret:ssid->id;
}