Beispiel #1
0
/* Add support for Windows Rally Vertical Pairing */
uint32
reg_proto_vendor_ext_vp(DevInfo *devInfo, BufferObj *msg)
{
#ifdef WCN_NET_SUPPORT
	CTlvVendorExt   vendorExt;
	uint16          data = 0;
	BufferObj       *pBufObj = NULL;

	if ((devInfo == NULL) || (msg == NULL)) {
		TUTRACE((TUTRACE_ERR, "RPROTO: Invalid parameters! \n"));
		return WPS_ERR_INVALID_PARAMETERS;
	}

	TUTRACE((TUTRACE_INFO, "RPROTO: Adding WCN-NET VP Vendor Extension \n"));

	pBufObj   = buffobj_new();
	data = (WPS_MS_VPI_TRANSPORT_UPNP << 8) | WPS_MS_VPI_PROFILE_REQ;

	if (pBufObj == NULL) {
		TUTRACE((TUTRACE_ERR, "RPROTO: Ran out of memory!\n"));
		return WPS_ERR_OUTOFMEMORY;
	}

	/* Add the VPI TLV */
	tlv_serialize_ve(MS_VENDOR_EXT_ID, WPS_MS_ID_VPI, pBufObj, &data, sizeof(data));

	/* Add the Transport UUID TLV */
	tlv_serialize_ve(MS_VENDOR_EXT_ID, WPS_MS_ID_TRANSPORT_UUID, pBufObj,
		devInfo->transport_uuid, SIZE_16_BYTES);

	/* Serialize subelemetns to Vendor Extension */
	vendorExt.vendorId = (uint8 *)MS_VENDOR_EXT_ID;
	vendorExt.vendorData = buffobj_GetBuf(pBufObj);
	vendorExt.dataLength = buffobj_Length(pBufObj);
	tlv_vendorExtWrite(&vendorExt, msg);

	buffobj_del(pBufObj);
	TUTRACE((TUTRACE_INFO, "RPROTO: Finished Adding WCN-NET VP Vendor Extension \n"));
#endif /* WCN_NET_SUPPORT */
	return WPS_SUCCESS;
}
Beispiel #2
0
static uint32
wps_setAssocRespIE(WPSAPI_T *g_mc, IN uint8 respType)
{
	uint32 ret;
	uint8 data8;
	CTlvVendorExt vendorExt;
	BufferObj *bufObj, *vendorExt_bufObj;
	DevInfo *info = g_mc->dev_info;

	bufObj = buffobj_new();
	if (!bufObj)
		return WPS_ERR_SYSTEM;

	vendorExt_bufObj = buffobj_new();
	if (vendorExt_bufObj == NULL) {
		buffobj_del(bufObj);
		return WPS_ERR_SYSTEM;
	}

	/* Version */
	data8 = WPS_VERSION;
	tlv_serialize(WPS_ID_VERSION, bufObj, &data8, WPS_ID_VERSION_S);

	/* Response Type */
	tlv_serialize(WPS_ID_RESP_TYPE, bufObj, &respType, WPS_ID_RESP_TYPE_S);

	/* WSC 2.0, add WFA vendor id and subelements to vendor extension attribute  */
	data8 = info->version2;
	subtlv_serialize(WPS_WFA_SUBID_VERSION2, vendorExt_bufObj, &data8,
		WPS_WFA_SUBID_VERSION2_S);

	/* Serialize subelemetns to Vendor Extension */
	vendorExt.vendorId = (uint8 *)WFA_VENDOR_EXT_ID;
	vendorExt.vendorData = buffobj_GetBuf(vendorExt_bufObj);
	vendorExt.dataLength = buffobj_Length(vendorExt_bufObj);
	tlv_vendorExtWrite(&vendorExt, bufObj);

	buffobj_del(vendorExt_bufObj);

#ifdef WFA_WPS_20_TESTBED
{
	char *pc_data;
	uint16 data16;

	/* New unknown attribute */
	pc_data = info->nattr_tlv;
	data16 = info->nattr_len;
	if (data16 && pc_data)
		buffobj_Append(bufObj, data16, pc_data);
}
#endif /* WFA_WPS_20_TESTBED */
	/* Send a pointer to the serialized data to Transport */
	if (0 != wps_set_wps_ie(g_mc->bcmwps, bufObj->pBase, bufObj->m_dataLength,
		WPS_IE_TYPE_SET_ASSOC_RESPONSE_IE)) {
		TUTRACE((TUTRACE_ERR, "wps_setAssocRespIE: call wps_set_wps_ie() failed\n"));
		ret = WPS_ERR_GENERIC;
	}
	else {
		TUTRACE((TUTRACE_ERR, "wps_setAssocRespIE: call wps_set_wps_ie() ok\n"));
		ret = WPS_SUCCESS;
	}

	/* bufObj will be destroyed when we exit this function */
	buffobj_del(bufObj);
	return ret;
}
Beispiel #3
0
/*
 * Name        : SetProbeRespIE
 * Description : Push WPS Probe Resp WPS IE information to transport
 * Arguments   :
 * Return type : uint32 - result of the operation
 */
static uint32
wps_setProbeRespIE(WPSAPI_T *g_mc, IN uint8 respType, IN uint8 scState,
	IN bool b_selRegistrar, IN uint16 devPwdId, IN uint16 selRegCfgMethods,
	uint8 *authorizedMacs_buf, int authorizedMacs_len)
{
	uint32 ret;
	BufferObj *bufObj, *vendorExt_bufObj;
	uint16 data16;
	uint8 data8, *p_data8;
	char *pc_data;
	CTlvPrimDeviceType tlvPrimDeviceType;
	CTlvVendorExt vendorExt;
	DevInfo *info = g_mc->dev_info;

	bufObj = buffobj_new();
	if (!bufObj)
		return WPS_ERR_SYSTEM;

	/* Version */
	data8 = WPS_VERSION;
	tlv_serialize(WPS_ID_VERSION, bufObj, &data8, WPS_ID_VERSION_S);

	/* Simple Config State */
	tlv_serialize(WPS_ID_SC_STATE, bufObj, &scState, WPS_ID_SC_STATE_S);

	/* AP Setup Locked - optional if false.  If implemented and TRUE, include this attribute. */
	/*
	 * tlv_serialize(WPS_ID_AP_SETUP_LOCKED, bufObj, &b_APSetupLocked,
	 * WPS_ID_AP_SETUP_LOCKED_S);
	 */

	/* Selected Registrar */
	tlv_serialize(WPS_ID_SEL_REGISTRAR, bufObj, &b_selRegistrar, WPS_ID_SEL_REGISTRAR_S);

	/*
	 * Selected Registrar Config Methods - optional, required if b_selRegistrar
	 * is true
	 * Device Password ID - optional, required if b_selRegistrar is true
	 * Enrollee UUID - optional, required if b_selRegistrar is true
	 */
	if (b_selRegistrar) {
		/* Device Password ID */
		tlv_serialize(WPS_ID_DEVICE_PWD_ID, bufObj, &devPwdId, WPS_ID_DEVICE_PWD_ID_S);
		/* Selected Registrar Config Methods */
		tlv_serialize(WPS_ID_SEL_REG_CFG_METHODS, bufObj, &selRegCfgMethods,
			WPS_ID_SEL_REG_CFG_METHODS_S);
		/* Per 1.0b spec, removed Enrollee UUID */
	}

	/* Response Type */
	tlv_serialize(WPS_ID_RESP_TYPE, bufObj, &respType, WPS_ID_RESP_TYPE_S);

	p_data8 = info->uuid;
	tlv_serialize(WPS_ID_UUID_E, bufObj, p_data8, SIZE_UUID);

	/* Manufacturer */
	pc_data = info->manufacturer;
	data16 = strlen(pc_data);
	tlv_serialize(WPS_ID_MANUFACTURER, bufObj, pc_data, data16);

	/* Model Name */
	pc_data = info->modelName;
	data16 = strlen(pc_data);
	tlv_serialize(WPS_ID_MODEL_NAME, bufObj, pc_data, data16);

	/* Model Number */
	pc_data = info->modelNumber;
	data16 = strlen(pc_data);
	tlv_serialize(WPS_ID_MODEL_NUMBER, bufObj, pc_data, data16);

	/* Serial Number */
	pc_data = info->serialNumber;
	data16 = strlen(pc_data);
	tlv_serialize(WPS_ID_SERIAL_NUM, bufObj, pc_data, data16);

	/*
	 * Primary Device Type
	 * This is a complex TLV, so will be handled differently
	 */
	tlvPrimDeviceType.categoryId = info->primDeviceCategory;
	tlvPrimDeviceType.oui = info->primDeviceOui;
	tlvPrimDeviceType.subCategoryId = info->primDeviceSubCategory;
	tlv_primDeviceTypeWrite(&tlvPrimDeviceType, bufObj);

	/* Device Name */
	pc_data = info->deviceName;
	data16 = strlen(pc_data);
	tlv_serialize(WPS_ID_DEVICE_NAME, bufObj, pc_data, data16);

	/* Config Methods */
	/*
	* 1: In WPS Test Plan 2.0.3, case 4.1.2 step4. APUT cannot use push button to add ER,
	* 2: In P2P Test Plan 4.2.1, PBC bit is checked to be disabled in WPS2.0.
	* 3: DMT PBC testing check the PBC method from CONFIG_METHODS field (for now, DMT
	* testing only avaliable on WPS 1.0.
	* Remove PBC in WPS 2.0 anyway.
	*/
	data16 = info->configMethods;
	data8 = info->version2;
	if (data8 >= WPS_VERSION2)
		data16 &= ~(WPS_CONFMET_VIRT_PBC | WPS_CONFMET_PHY_PBC);
	else
	{
		/* WPS 1.0 */
		if (scState == WPS_SCSTATE_UNCONFIGURED)
		{
			data16 &= ~WPS_CONFMET_PBC;
		}
	}
	tlv_serialize(WPS_ID_CONFIG_METHODS, bufObj, &data16, WPS_ID_CONFIG_METHODS_S);

	/* RF Bands - optional */
	data8 = info->rfBand;
	if (data8 == 3)
		tlv_serialize(WPS_ID_RF_BAND, bufObj, &data8, WPS_ID_RF_BAND_S);

	/* WSC 2.0, add WFA vendor id and subelements to vendor extension attribute  */
	data8 = info->version2;
	if (data8 >= WPS_VERSION2) {
		vendorExt_bufObj = buffobj_new();
		if (vendorExt_bufObj == NULL) {
			buffobj_del(bufObj);
			return WPS_ERR_SYSTEM;
		}

		subtlv_serialize(WPS_WFA_SUBID_VERSION2, vendorExt_bufObj,
			&data8, WPS_WFA_SUBID_VERSION2_S);

		/* AuthorizedMACs */
		if (authorizedMacs_buf && authorizedMacs_len) {
			subtlv_serialize(WPS_WFA_SUBID_AUTHORIZED_MACS, vendorExt_bufObj,
				authorizedMacs_buf, authorizedMacs_len);
		}

		/* Serialize subelemetns to Vendor Extension */
		vendorExt.vendorId = (uint8 *)WFA_VENDOR_EXT_ID;
		vendorExt.vendorData = buffobj_GetBuf(vendorExt_bufObj);
		vendorExt.dataLength = buffobj_Length(vendorExt_bufObj);
		tlv_vendorExtWrite(&vendorExt, bufObj);

		buffobj_del(vendorExt_bufObj);
#ifdef WFA_WPS_20_TESTBED
		/* New unknown attribute */
		pc_data = info->nattr_tlv;
		data16 = info->nattr_len;
		if (data16 && pc_data)
			buffobj_Append(bufObj, data16, pc_data);
#endif /* WFA_WPS_20_TESTBED */
	}

	/* Send a pointer to the serialized data to Transport */
	if (0 != wps_set_wps_ie(g_mc->bcmwps, bufObj->pBase, bufObj->m_dataLength,
		WPS_IE_TYPE_SET_PROBE_RESPONSE_IE)) {
		TUTRACE((TUTRACE_ERR, "wps_setProbeRespIE: call wps_set_wps_ie() failed\n"));
		ret = WPS_ERR_GENERIC;
	}
	else {
		TUTRACE((TUTRACE_ERR, "wps_setProbeRespIE: call wps_set_wps_ie() ok\n"));
		ret = WPS_SUCCESS;
	}

	/* bufObj will be destroyed when we exit this function */
	buffobj_del(bufObj);
	return ret;
}
Beispiel #4
0
/*
 * Name        : SetBeaconIE
 * Description : Push Beacon WPS IE information to transport
 * Arguments   : IN bool b_configured - is the AP configured?
 * IN bool b_selRegistrar - is this flag set?
 * IN uint16 devPwdId - valid if b_selRegistrar is true
 * IN uint16 selRegCfgMethods - valid if b_selRegistrar is true
 * Return type : uint32 - result of the operation
 */
static uint32
wps_setBeaconIE(WPSAPI_T *g_mc, IN bool b_configured, IN bool b_selRegistrar,
	IN uint16 devPwdId, IN uint16 selRegCfgMethods, uint8 *authorizedMacs_buf,
	int authorizedMacs_len)
{
	uint32 ret;
	uint8 data8;
	uint8 *p_data8;
	CTlvVendorExt vendorExt;
	DevInfo *info = g_mc->dev_info;

	BufferObj *bufObj, *vendorExt_bufObj;

	bufObj = buffobj_new();
	if (!bufObj)
		return WPS_ERR_SYSTEM;

	/* Version */
	data8 = WPS_VERSION;
	tlv_serialize(WPS_ID_VERSION, bufObj, &data8, WPS_ID_VERSION_S);

	/* Simple Config State */
	if (b_configured)
		data8 = WPS_SCSTATE_CONFIGURED;
	else
		data8 = WPS_SCSTATE_UNCONFIGURED;
	tlv_serialize(WPS_ID_SC_STATE, bufObj, &data8, WPS_ID_SC_STATE_S);

	/*
	 * AP Setup Locked - optional if false.  If implemented and TRUE, include this attribute.
	 * CTlvAPSetupLocked(WPS_ID_AP_SETUP_LOCKED, bufObj, &b_APSetupLocked);
	 *
	 * Selected Registrar - optional
	 * Add this TLV only if b_selRegistrar is true
	 */
	if (b_selRegistrar) {
		tlv_serialize(WPS_ID_SEL_REGISTRAR, bufObj, &b_selRegistrar,
			WPS_ID_SEL_REGISTRAR_S);
		/* Add in other related params as well Device Password ID */
		tlv_serialize(WPS_ID_DEVICE_PWD_ID, bufObj, &devPwdId, WPS_ID_DEVICE_PWD_ID_S);
		/* Selected Registrar Config Methods */
		tlv_serialize(WPS_ID_SEL_REG_CFG_METHODS, bufObj,
			&selRegCfgMethods, WPS_ID_SEL_REG_CFG_METHODS_S);
		/* Enrollee UUID removed */
	}

	data8 = info->rfBand;
	/* dual band, it's become require */
	if (data8 == 3) {
		p_data8 = info->uuid;
		tlv_serialize(WPS_ID_UUID_E, bufObj, p_data8, SIZE_UUID);
		tlv_serialize(WPS_ID_RF_BAND, bufObj, &data8, WPS_ID_RF_BAND_S);
	}

	/* WSC 2.0,  support WPS V2 or not */
	data8 = info->version2;
	if (data8 >= WPS_VERSION2) {
		vendorExt_bufObj = buffobj_new();
		if (vendorExt_bufObj == NULL) {
			buffobj_del(bufObj);
			return WPS_ERR_SYSTEM;
		}

		/* WSC 2.0 */
		subtlv_serialize(WPS_WFA_SUBID_VERSION2, vendorExt_bufObj,
			&data8, WPS_WFA_SUBID_VERSION2_S);
		/* AuthorizedMACs */
		if (authorizedMacs_buf && authorizedMacs_len) {
			subtlv_serialize(WPS_WFA_SUBID_AUTHORIZED_MACS, vendorExt_bufObj,
				authorizedMacs_buf, authorizedMacs_len);
		}

		/* Serialize subelemetns to Vendor Extension */
		vendorExt.vendorId = (uint8 *)WFA_VENDOR_EXT_ID;
		vendorExt.vendorData = buffobj_GetBuf(vendorExt_bufObj);
		vendorExt.dataLength = buffobj_Length(vendorExt_bufObj);
		tlv_vendorExtWrite(&vendorExt, bufObj);

		buffobj_del(vendorExt_bufObj);
#ifdef WFA_WPS_20_TESTBED
{
	char *pc_data;
	uint16 data16;

	/* New unknown attribute */
	pc_data = info->nattr_tlv;
	data16 = info->nattr_len;
	if (data16 && pc_data)
		buffobj_Append(bufObj, data16, pc_data);
}
#endif /* WFA_WPS_20_TESTBED */
	}

	/* Send a pointer to the serialized data to Transport */
	if (0 != wps_set_wps_ie(g_mc->bcmwps, bufObj->pBase, bufObj->m_dataLength,
		1 /* WPS_IE_TYPE_SET_BEACON_IE */ )) {
		TUTRACE((TUTRACE_ERR, "MC_SetBeaconIE: call to trans->SetBeaconIE() failed\n"));
		ret = WPS_ERR_GENERIC;
	}
	else {
		TUTRACE((TUTRACE_ERR, "MC_SetBeaconIE: call to trans->SetBeaconIE() ok\n"));
		ret = WPS_SUCCESS;
	}

	buffobj_del(bufObj);
	return ret;
}
Beispiel #5
0
uint32
nfc_utils_build_cfg(DevInfo *info, uint8 *buf, uint *buflen)
{
	char *p_nwKey, *cp_data;
	uint8 *p_macAddr, wep_exist = 0, version = WPS_VERSION;
	uint16 data16;
	uint32 ret = WPS_SUCCESS, nwKeyLen = 0;
	BufferObj *bufObj = NULL, *vendorExt_bufObj = NULL;
	CTlvVendorExt vendorExt;
	CTlvCredential *p_tlvCred = NULL;

	TUTRACE((TUTRACE_NFC, "Build NFC Configuration\n"));

	if (info == NULL || buf == NULL || *buflen == 0) {
		TUTRACE((TUTRACE_NFC, "nfc_utils_build_cfg: Invalid arguments\n"));
		return WPS_ERR_SYSTEM;
	}

	if ((bufObj = buffobj_new()) == NULL) {
		TUTRACE((TUTRACE_NFC, "nfc_utils_build_cfg: Out of memory\n"));
		return WPS_ERR_OUTOFMEMORY;
	}

	/* Version */
	tlv_serialize(WPS_ID_VERSION, bufObj, &version, WPS_ID_VERSION_S);

	/* Credential */
	if ((p_tlvCred = (CTlvCredential *)malloc(sizeof(CTlvCredential))) == NULL) {
		TUTRACE((TUTRACE_NFC, "nfc_utils_build_cfg: Out of memory\n"));
		ret = WPS_ERR_OUTOFMEMORY;
		goto error;
	}
	memset(p_tlvCred, 0, sizeof(CTlvCredential));

	/* Credential items */
	/* nwIndex */
	tlv_set(&p_tlvCred->nwIndex, WPS_ID_NW_INDEX, (void *)1, 0);

	/* ssid */
	cp_data = info->ssid;
	data16 = strlen(cp_data);
	tlv_set(&p_tlvCred->ssid, WPS_ID_SSID, cp_data, data16);

	/* auth */
	if (info->auth)
		data16 = WPS_AUTHTYPE_SHARED;
	else if (devinfo_getKeyMgmtType(info) == WPS_WL_AKM_PSK)
		data16 = WPS_AUTHTYPE_WPAPSK;
	else if (devinfo_getKeyMgmtType(info) == WPS_WL_AKM_PSK2)
		data16 = WPS_AUTHTYPE_WPA2PSK;
	else if (devinfo_getKeyMgmtType(info) == WPS_WL_AKM_BOTH)
		data16 = WPS_AUTHTYPE_WPAPSK | WPS_AUTHTYPE_WPA2PSK;
	else
		data16 = WPS_AUTHTYPE_OPEN;
	tlv_set(&p_tlvCred->authType, WPS_ID_AUTH_TYPE, UINT2PTR(data16), 0);

	/* encrType */
	if (info->auth)
		data16 = WPS_ENCRTYPE_WEP;
	else if (data16 == WPS_AUTHTYPE_OPEN) {
		if (info->wep)
			data16 = WPS_ENCRTYPE_WEP;
		else
			data16 = WPS_ENCRTYPE_NONE;
	}
	else
		data16 = info->crypto;
	tlv_set(&p_tlvCred->encrType, WPS_ID_ENCR_TYPE, UINT2PTR(data16), 0);

	if (data16 == WPS_ENCRTYPE_WEP)
		wep_exist = 1;

	/* nwKeyIndex
	 * WSC 2.0, "Network Key Index" deprecated - only included by WSC 1.0 devices.
	 * Ignored by WSC 2.0 or newer devices.
	 */
	if (info->version2 < WPS_VERSION2) {
		tlv_set(&p_tlvCred->nwKeyIndex, WPS_ID_NW_KEY_INDEX, (void *)1, 0);
	}

	/* nwKey */
	p_nwKey = info->nwKey;
	nwKeyLen = strlen(info->nwKey);
	tlv_set(&p_tlvCred->nwKey, WPS_ID_NW_KEY, p_nwKey, nwKeyLen);

	/* enrollee's mac */
	p_macAddr = info->peerMacAddr;
	data16 = SIZE_MAC_ADDR;
	tlv_set(&p_tlvCred->macAddr, WPS_ID_MAC_ADDR, p_macAddr, data16);

	/* WepKeyIdx */
	if (wep_exist)
		tlv_set(&p_tlvCred->WEPKeyIndex, WPS_ID_WEP_TRANSMIT_KEY,
			UINT2PTR(info->wepKeyIdx), 0);

	/* WSC 2.0, WFA "Network Key Shareable" subelement */
	if (info->version2 >= WPS_VERSION2) {
		/* Always shareable */
		data16 = 1;
		subtlv_set(&p_tlvCred->nwKeyShareable, WPS_WFA_SUBID_NW_KEY_SHAREABLE,
			UINT2PTR(data16), 0);
	}
	tlv_credentialWrite(p_tlvCred, bufObj);

	/* Version2 */
	if (info->version2 >= WPS_VERSION2) {
		if ((vendorExt_bufObj = buffobj_new()) == NULL) {
			TUTRACE((TUTRACE_NFC, "nfc_utils_build_cfg: Out of memory\n"));
			ret = WPS_ERR_OUTOFMEMORY;
			goto error;
		}

		subtlv_serialize(WPS_WFA_SUBID_VERSION2, vendorExt_bufObj,
			&info->version2, WPS_WFA_SUBID_VERSION2_S);

		/* Serialize subelemetns to Vendor Extension */
		vendorExt.vendorId = (uint8 *)WFA_VENDOR_EXT_ID;
		vendorExt.vendorData = buffobj_GetBuf(vendorExt_bufObj);
		vendorExt.dataLength = buffobj_Length(vendorExt_bufObj);
		tlv_vendorExtWrite(&vendorExt, bufObj);
	}

	/* Check copy back avaliable buf length */
	if (*buflen < buffobj_Length(bufObj)) {
		TUTRACE((TUTRACE_NFC, "nfc_utils_build_cfg: In buffer len too short\n"));
		ret = WPS_ERR_SYSTEM;
		goto error;
	}

	/* Copy back data and length */
	*buflen = buffobj_Length(bufObj);
	memcpy(buf, buffobj_GetBuf(bufObj), buffobj_Length(bufObj));

error:
	/* Free local vendorExt_bufObj */
	if (vendorExt_bufObj)
		buffobj_del(vendorExt_bufObj);

	/* Free local p_tlvCred */
	if (p_tlvCred)
		tlv_credentialDelete(p_tlvCred, 0);

	/* Free local bufObj */
	if (bufObj)
		buffobj_del(bufObj);

	return ret;
}
Beispiel #6
0
uint32
nfc_utils_build_pw(DevInfo *info, uint8 *buf, uint *buflen)
{
	uint8 version = WPS_VERSION;
	uint32 ret = WPS_SUCCESS;
	BufferObj *bufObj = NULL, *vendorExt_bufObj = NULL;
	CTlvVendorExt vendorExt;
	CTlvOobDevPwd oobDevPwd;
	unsigned char hex_pin[SIZE_32_BYTES];
	int hex_pin_len;

	TUTRACE((TUTRACE_NFC, "Build NFC Password\n"));

	if (info == NULL || buf == NULL || *buflen == 0) {
		TUTRACE((TUTRACE_NFC, "nfc_utils_build_pw: Invalid arguments\n"));
		return WPS_ERR_SYSTEM;
	}

	if ((bufObj = buffobj_new()) == NULL) {
		TUTRACE((TUTRACE_NFC, "nfc_utils_build_pw: Out of memory\n"));
		return WPS_ERR_OUTOFMEMORY;
	}

	/* Version */
	tlv_serialize(WPS_ID_VERSION, bufObj, &version, WPS_ID_VERSION_S);

	/* OOB Device Password */
	oobDevPwd.publicKeyHash = info->pub_key_hash;
	oobDevPwd.pwdId = info->devPwdId;

	/* Do String to Hex translation */
	hex_pin_len = wps_str2hex(hex_pin, sizeof(hex_pin), info->pin);
	if (hex_pin_len == 0) {
		TUTRACE((TUTRACE_NFC, "nfc_utils_build_pw: invalid parameters\n"));
		ret = WPS_ERR_INVALID_PARAMETERS;
		goto error;
	}

	oobDevPwd.ip_devPwd = hex_pin;
	oobDevPwd.devPwdLength = hex_pin_len;
	tlv_oobDevPwdWrite(&oobDevPwd, bufObj);

	/* Version2 */
	if (info->version2 >= WPS_VERSION2) {
		if ((vendorExt_bufObj = buffobj_new()) == NULL) {
			TUTRACE((TUTRACE_NFC, "nfc_utils_build_pw: Out of memory\n"));
			ret = WPS_ERR_OUTOFMEMORY;
			goto error;
		}

		subtlv_serialize(WPS_WFA_SUBID_VERSION2, vendorExt_bufObj,
			&info->version2, WPS_WFA_SUBID_VERSION2_S);

		/* Serialize subelemetns to Vendor Extension */
		vendorExt.vendorId = (uint8 *)WFA_VENDOR_EXT_ID;
		vendorExt.vendorData = buffobj_GetBuf(vendorExt_bufObj);
		vendorExt.dataLength = buffobj_Length(vendorExt_bufObj);
		tlv_vendorExtWrite(&vendorExt, bufObj);
	}

	/* Check copy back avaliable buf length */
	if (*buflen < buffobj_Length(bufObj)) {
		TUTRACE((TUTRACE_NFC, "nfc_utils_build_cfg: In buffer len too short\n"));
		ret = WPS_ERR_SYSTEM;
		goto error;
	}

	/* Copy back data and length */
	*buflen = buffobj_Length(bufObj);
	memcpy(buf, buffobj_GetBuf(bufObj), buffobj_Length(bufObj));

error:
	/* Free local vendorExt_bufObj */
	if (vendorExt_bufObj)
		buffobj_del(vendorExt_bufObj);

	/* Free local bufObj */
	if (bufObj)
		buffobj_del(bufObj);

	return ret;
}