void reg_proto_encrypt_data(BufferObj *plainText, BufferObj *encrKey, BufferObj *authKey, BufferObj *cipherText, BufferObj *iv) { BufferObj *buf = buffobj_new(); uint8 ivBuf[SIZE_128_BITS]; /* 10 rounds for cbc 128 = (10+1) * 4 uint32 */ uint32 rk[44]; uint8 outBuf[1024]; int encrypt_len; if (!buf) return; if (plainText->m_dataLength == 0) { TUTRACE((TUTRACE_ERR, "Invalid parameters \n")); buffobj_del(buf); return; } /* Generate a random iv */ RAND_bytes(ivBuf, SIZE_128_BITS); buffobj_Reset(iv); buffobj_Append(iv, SIZE_128_BITS, ivBuf); /* Now encrypt the plaintext and mac using the encryption key and IV. */ buffobj_Append(buf, plainText->m_dataLength, plainText->pBase); TUTRACE((TUTRACE_ERR, "RPROTO: calling encryption of %d bytes\n", buf->m_dataLength)); rijndaelKeySetupEnc(rk, encrKey->pBase, 128); encrypt_len = aes_cbc_encrypt_pad(rk, 16, ivBuf, buf->m_dataLength, plainText->pBase, outBuf, PAD_LEN_PADDING); buffobj_Append(cipherText, encrypt_len, outBuf); buffobj_del(buf); }
void reg_proto_derivekey(BufferObj *KDK, BufferObj *prsnlString, uint32 keyBits, BufferObj *key) { uint32 i = 0, iterations = 0; BufferObj *input, *output; uint8 hmac[SIZE_256_BITS]; uint32 hmacLen = 0; uint8 *inPtr; uint32 temp; input = buffobj_new(); if (!input) return; output = buffobj_new(); if (!output) { buffobj_del(input); return; } TUTRACE((TUTRACE_INFO, "RPROTO: Deriving a key of %d bits\n", keyBits)); iterations = ((keyBits/8) + PRF_DIGEST_SIZE - 1)/PRF_DIGEST_SIZE; /* * Prepare the input buffer. During the iterations, we need only replace the * value of i at the start of the buffer. */ temp = WpsHtonl(i); buffobj_Append(input, SIZE_4_BYTES, (uint8 *)&temp); buffobj_Append(input, prsnlString->m_dataLength, prsnlString->pBase); temp = WpsHtonl(keyBits); buffobj_Append(input, SIZE_4_BYTES, (uint8 *)&temp); inPtr = input->pBase; for (i = 0; i < iterations; i++) { /* Set the current value of i at the start of the input buffer */ *(uint32 *)inPtr = WpsHtonl(i+1) ; /* i should start at 1 */ hmac_sha256(KDK->pBase, SIZE_256_BITS, input->pBase, input->m_dataLength, hmac, &hmacLen); buffobj_Append(output, hmacLen, hmac); } /* Sanity check */ if (keyBits/8 > output->m_dataLength) { TUTRACE((TUTRACE_ERR, "RPROTO: Key derivation generated less bits " "than asked\n")); buffobj_del(output); buffobj_del(input); return; } /* * We now have at least the number of key bits requested. * Return only the number of bits asked for. Discard the excess. */ buffobj_Append(key, keyBits/8, output->pBase); buffobj_del(output); buffobj_del(input); TUTRACE((TUTRACE_INFO, "RPROTO: End Deriving a key of %d bits\n", keyBits)); }
/* 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; }
/* * NOTE: The caller MUST call tlv_delete(ssrmsg->authorizedMacs, 1) to free memory which * allocated in this fcuntion. */ int wps_get_upnpDevSSR(WPSAPI_T *g_mc, void *p_cbData, uint32 length, CTlvSsrIE *ssrmsg) { int ret = WPS_CONT; uint8 data8; DevInfo *info = g_mc->dev_info; TUTRACE((TUTRACE_INFO, "wps_get_upnpDevSSR\n")); if (info->sc_mode == SCMODE_AP_REGISTRAR) { BufferObj *vendorExt_bufObj = NULL; BufferObj *wlidcardMac_bufObj = NULL; /* De-serialize the data to get the TLVs */ BufferObj *bufObj = buffobj_new(); if (!bufObj) return WPS_ERR_SYSTEM; buffobj_dserial(bufObj, (uint8 *)p_cbData, length); memset(ssrmsg, 0, sizeof(CTlvSsrIE)); /* Version */ tlv_dserialize(&ssrmsg->version, WPS_ID_VERSION, bufObj, 0, 0); /* Selected Registrar */ tlv_dserialize(&ssrmsg->selReg, WPS_ID_SEL_REGISTRAR, bufObj, 0, 0); /* Device Password ID */ tlv_dserialize(&ssrmsg->devPwdId, WPS_ID_DEVICE_PWD_ID, bufObj, 0, 0); /* Selected Registrar Config Methods */ tlv_dserialize(&ssrmsg->selRegCfgMethods, WPS_ID_SEL_REG_CFG_METHODS, bufObj, 0, 0); /* WSC 2.0 */ data8 = info->version2; if (data8 >= WPS_VERSION2) { /* Check subelement in WFA Vendor Extension */ if (tlv_find_vendorExtParse(&ssrmsg->vendorExt, bufObj, (uint8 *)WFA_VENDOR_EXT_ID) != 0) goto add_wildcard_mac; /* Deserialize subelement */ vendorExt_bufObj = buffobj_new(); if (!vendorExt_bufObj) { buffobj_del(bufObj); return -1; } buffobj_dserial(vendorExt_bufObj, ssrmsg->vendorExt.vendorData, ssrmsg->vendorExt.dataLength); /* Get Version2 and AuthorizedMACs subelement */ if (subtlv_dserialize(&ssrmsg->version2, WPS_WFA_SUBID_VERSION2, vendorExt_bufObj, 0, 0) == 0) { /* AuthorizedMACs, <= 30B */ subtlv_dserialize(&ssrmsg->authorizedMacs, WPS_WFA_SUBID_AUTHORIZED_MACS, vendorExt_bufObj, 0, 0); } /* Add wildcard MAC when authorized mac not specified */ if (ssrmsg->authorizedMacs.subtlvbase.m_len == 0) { add_wildcard_mac: /* * If the External Registrar is WSC version 1.0 it * will not have included an AuthorizedMACs subelement. * In this case the AP shall add the wildcard MAC Address * (FF:FF:FF:FF:FF:FF) in an AuthorizedMACs subelement in * Beacon and Probe Response frames */ wlidcardMac_bufObj = buffobj_new(); if (!wlidcardMac_bufObj) { buffobj_del(vendorExt_bufObj); buffobj_del(bufObj); return -1; } /* Serialize the wildcard_authorizedMacs to wlidcardMac_Obj */ subtlv_serialize(WPS_WFA_SUBID_AUTHORIZED_MACS, wlidcardMac_bufObj, (char *)wildcard_authorizedMacs, SIZE_MAC_ADDR); buffobj_Rewind(wlidcardMac_bufObj); /* * De-serialize the wlidcardMac_Obj data to get the TLVs * Do allocation, because wlidcardMac_bufObj will be freed here but * ssrmsg->authorizedMacs return and used by caller. */ subtlv_dserialize(&ssrmsg->authorizedMacs, WPS_WFA_SUBID_AUTHORIZED_MACS, wlidcardMac_bufObj, 0, 1); /* Need to free it */ } /* Get UUID-R after WFA-Vendor Extension (wpa_supplicant use this way) */ tlv_find_dserialize(&ssrmsg->uuid_R, WPS_ID_UUID_R, bufObj, 0, 0); } /* Other... */ if (bufObj) buffobj_del(bufObj); if (wlidcardMac_bufObj) buffobj_del(wlidcardMac_bufObj); if (vendorExt_bufObj) buffobj_del(vendorExt_bufObj); ret = WPS_SUCCESS; } return ret; }
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; }
/* * 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; }
/* * 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; }
int wps_processMsg(void *mc_dev, void *inbuffer, uint32 in_len, void *outbuffer, uint32 *out_len, TRANSPORT_TYPE m_transportType) { WPSAPI_T *g_mc = (WPSAPI_T *)mc_dev; RegData *regInfo; EnrSM *e; int ret = WPS_CONT; if (!g_mc) return WPS_MESSAGE_PROCESSING_ERROR; if (wps_get_mode(g_mc) == SCMODE_AP_ENROLLEE) { if (g_mc->mp_enrSM) { g_mc->mp_enrSM->reg_info->transportType = m_transportType; /* Pre-process upnp */ ret = wps_enrUpnpGetDeviceInfoCheck(g_mc->mp_enrSM, inbuffer, in_len, outbuffer, out_len); if (ret != WPS_CONT) { if (ret == WPS_SUCCESS) return WPS_CONT; else return ret; } /* Hacking, * set regInfo's e_lastMsgSent to M1, m_m2dStatus to SM_AWAIT_M2 and * regInfo's e_smState to CONTINUE, * and create M1 to get regInfo's outMsg which needed in M2 process */ e = g_mc->mp_enrSM; regInfo = e->reg_info; if (START == regInfo->e_smState && (regInfo->dev_info->flags & DEVINFO_FLAG_PRE_NONCE)) { uint32 msgType = 0, err; BufferObj *inMsg, *outMsg; inMsg = buffobj_new(); if (!inMsg) return WPS_ERR_SYSTEM; buffobj_dserial(inMsg, inbuffer, in_len); err = reg_proto_get_msg_type(&msgType, inMsg); buffobj_del(inMsg); if (WPS_SUCCESS == err && WPS_ID_MESSAGE_M2 == msgType) { outMsg = buffobj_setbuf((uint8 *)outbuffer, *out_len); if (!outMsg) return WPS_ERR_SYSTEM; memcpy(regInfo->enrolleeNonce, regInfo->dev_info->pre_nonce, SIZE_128_BITS); e->reg_info->e_lastMsgSent = M1; /* Set the m2dstatus. */ e->m_m2dStatus = SM_AWAIT_M2; /* set the message state to CONTINUE */ e->reg_info->e_smState = CONTINUE; reg_proto_create_m1(regInfo, outMsg); buffobj_del(outMsg); } } ret = enr_sm_step(g_mc->mp_enrSM, in_len, ((uint8 *)inbuffer), ((uint8 *)outbuffer), out_len); } } else { if (g_mc->mp_regSM) { g_mc->mp_regSM->reg_info->transportType = m_transportType; /* Pre-process upnp */ ret = wps_regUpnpForwardingCheck(g_mc->mp_regSM, inbuffer, in_len, outbuffer, out_len); if (ret != WPS_CONT) { return ret; } ret = reg_sm_step(g_mc->mp_regSM, in_len, ((uint8 *)inbuffer), ((uint8 *)outbuffer), out_len); } } return ret; }
uint32 wps_regUpnpForwardingCheck(RegSM *r, void *inbuffer, uint32 in_len, void *outbuffer, uint32 *out_len) { uint32 msgType = 0, err = WPS_SUCCESS, retVal = WPS_CONT; TRANSPORT_TYPE trType; BufferObj *inMsg = NULL, *outMsg = NULL; if (false == r->reg_info->initialized) { TUTRACE((TUTRACE_ERR, "REGSM: Not yet initialized.\n")); return WPS_ERR_NOT_INITIALIZED; } /* Irrespective of whether the local registrar is enabled or whether we're * using an external registrar, we need to send a WPS_Start over EAP to * kickstart the protocol. * If we send a WPS_START msg, we don't need to do anything else i.e. * invoke the local registrar or pass the message over UPnP */ if ((!in_len) && (START == r->reg_info->e_smState) && ((TRANSPORT_TYPE_EAP == r->reg_info->transportType) || (TRANSPORT_TYPE_UPNP_CP == r->reg_info->transportType))) { err = wps_sendStartMessage(r->g_mc, r->reg_info->transportType); if (WPS_SUCCESS != err) { TUTRACE((TUTRACE_ERR, "REGSM: SendStartMessage failed. Err = %d\n", err)); } return WPS_CONT; } /* Now send the message over UPnP. Else, if the message has come over UPnP * send it over EAP. * if(m_passThruEnabled) */ /* temporarily disable forwarding to/from UPnP if we've already sent M2 * this is a stop-gap measure to prevent multiple registrars from cluttering * up the EAP session. */ if ((r->m_passThruEnabled) && (!r->m_sentM2) && wps_get_mode(r->g_mc) == SCMODE_AP_REGISTRAR) { if ((inMsg = buffobj_new()) == NULL) return WPS_ERR_SYSTEM; if (in_len) { buffobj_dserial(inMsg, inbuffer, in_len); err = reg_proto_get_msg_type(&msgType, inMsg); } switch (r->reg_info->transportType) { case TRANSPORT_TYPE_EAP: /* EAP to UPnP: * if add client was performed by AP, skip this forward * if (getBuiltInStart()) * break; */ if (r->reg_info->dev_info->b_ap) trType = TRANSPORT_TYPE_UPNP_DEV; else trType = TRANSPORT_TYPE_UPNP_CP; /* recvd from EAP, send over UPnP */ if (msgType != WPS_ID_MESSAGE_ACK) { TUTRACE((TUTRACE_INFO, "REGSM: Forwarding message from " "EAP to UPnP.\n")); TUTRACE((TUTRACE_INFO, "\n###EAP to UPnP msgType=%x (%s)" " ###\n", msgType, wps_msg_type_str(msgType))); err = wps_sendMsg(r->g_mc, trType, (char *)inbuffer, in_len); } /* Now check to see if the EAP message is a WPS_NACK. If so, * terminate the EAP connection with an EAP-Fail. * if (msgType == WPS_ID_MESSAGE_NACK && WPS_SUCCESS == err) { */ if (msgType == WPS_ID_MESSAGE_NACK) { TUTRACE((TUTRACE_ERR, "REGSM: Notifying MC of failure.\n")); /* reset the SM */ reg_sm_restartsm(r); retVal = WPS_MESSAGE_PROCESSING_ERROR; break; } if ((WPS_SUCCESS == err) && (msgType == WPS_ID_MESSAGE_DONE)) { TUTRACE((TUTRACE_INFO, "REGSM: Send EAP fail when " "DONE or ACK (type=%x).\n", msgType)); retVal = WPS_SUCCESS; break; } break; default: /* UPnP to EAP: */ TUTRACE((TUTRACE_INFO, "REGSM: Forwarding message from UPnP to EAP.\n")); /* recvd over UPNP, send it out over EAP */ TUTRACE((TUTRACE_INFO, "\n======== GetDeviceInfo=%d =======\n", wps_getUpnpDevGetDeviceInfo(r->g_mc))); if (in_len) { TUTRACE((TUTRACE_INFO, "\n###UPnP to EAP msgType=%x (%s) ###\n", msgType, wps_msg_type_str(msgType))); if (WPS_SUCCESS == err && msgType == WPS_ID_MESSAGE_M2D) { TUTRACE((TUTRACE_INFO, "\n ==received M2D ==\n")); } } if (wps_getUpnpDevGetDeviceInfo(r->g_mc)) { outMsg = buffobj_setbuf(outbuffer, *out_len); if (!outMsg) { retVal = WPS_ERR_SYSTEM; break; } wps_setUpnpDevGetDeviceInfo(r->g_mc, false); err = reg_proto_create_devinforsp(r->reg_info, outMsg); if (WPS_SUCCESS != err) { TUTRACE((TUTRACE_ERR, "BuildMessageM1: %d\n", err)); } else { /* Now send the message to the transport */ err = wps_sendMsg(r->g_mc, r->reg_info->transportType, (char *)outMsg->pBase, outMsg->m_dataLength); } if (WPS_SUCCESS != err) { r->reg_info->e_smState = FAILURE; TUTRACE((TUTRACE_ERR, "ENRSM: TrWrite generated an " "error: %d\n", err)); } } if (in_len) { if (wps_regUpnpERFilter(r, inMsg, msgType) == WPS_CONT) break; err = wps_sendMsg(r->g_mc, TRANSPORT_TYPE_EAP, (char *)inbuffer, in_len); } break; } } if (inMsg) buffobj_del(inMsg); if (outMsg) buffobj_del(outMsg); return retVal; }
uint32 nfc_utils_parse_pw(WpsOobDevPw *devpw, uint8 wsp_version2, uint8 *buf, uint buflen) { uint32 ret = WPS_SUCCESS; char *cp_data; uint16 data16; BufferObj *bufObj = NULL; BufferObj *vendorExt_bufObj = NULL; CTlvVersion version; CSubTlvVersion2 version2; CTlvVendorExt vendorExt; CTlvOobDevPwd *p_oobDevPwd = NULL; /* Sanity check */ if (devpw == NULL || buf == NULL || buflen == 0) { TUTRACE((TUTRACE_NFC, "Pase WPS PW: Invalid parameters!\n")); ret = WPS_ERR_INVALID_PARAMETERS; goto error; } if (buflen < 7) { TUTRACE((TUTRACE_NFC, "Pase WPS PW: buf length too short!\n")); ret = WPS_ERR_INVALID_PARAMETERS; goto error; } if (buf[5] != 0x10 || buf[6] != 0x2C) { TUTRACE((TUTRACE_NFC, "Pase WPS PW: Not a Password Token!\n")); ret = WPS_ERR_INVALID_PARAMETERS; goto error; } /* Dserial raw data to bufObj */ bufObj = buffobj_new(); if (bufObj == NULL) { TUTRACE((TUTRACE_NFC, "Pase WPS PW: Malloc fail!\n")); ret = WPS_ERR_OUTOFMEMORY; goto error; } WPS_HexDumpAscii("NFC_UTILS_PARSE_PW", -1, buf, buflen); buffobj_dserial(bufObj, buf, buflen); /* Version 1 */ if (tlv_dserialize(&version, WPS_ID_VERSION, bufObj, 0, 0) != 0) { TUTRACE((TUTRACE_NFC, "Pase WPS PW: TLV missing\n")); ret = RPROT_ERR_REQD_TLV_MISSING; goto error; } /* Must be 0x10, See WSC2.0 Clause 7.9 Version Negotiation */ if (version.m_data != WPS_VERSION) { TUTRACE((TUTRACE_NFC, "Pase WPS PW: Message version should always set to 1\n")); ret = RPROT_ERR_INCOMPATIBLE; goto error; } /* OOB Device Password */ p_oobDevPwd = (CTlvOobDevPwd *)malloc(sizeof(CTlvOobDevPwd)); if (!p_oobDevPwd) { TUTRACE((TUTRACE_NFC, "Pase WPS PW: Malloc fail!\n")); ret = WPS_ERR_OUTOFMEMORY; goto error; } memset(p_oobDevPwd, 0, sizeof(CTlvOobDevPwd)); if (tlv_oobDevPwdParse(p_oobDevPwd, bufObj) != 0) { ret = WPS_ERR_SYSTEM; goto error; } /* Save CTlvOobDevPwd to WpsOobDevPw */ memcpy(devpw->pub_key_hash, p_oobDevPwd->publicKeyHash, SIZE_160_BITS); devpw->devPwdId = p_oobDevPwd->pwdId; memcpy(devpw->pin, p_oobDevPwd->ip_devPwd, p_oobDevPwd->devPwdLength); devpw->pin_len = p_oobDevPwd->devPwdLength; /* Version2, here you don't is peer WSC 2.0 or not */ if (wsp_version2 >= WPS_VERSION2) { if (tlv_find_vendorExtParse(&vendorExt, bufObj, (uint8 *)WFA_VENDOR_EXT_ID) != 0) { TUTRACE((TUTRACE_NFC, "Pase WPS PW: Cannot find vendor extension\n")); /* ret = RPROT_ERR_INCOMPATIBLE; */ goto error; } /* Deserialize subelement */ if ((vendorExt_bufObj = buffobj_new()) == NULL) { TUTRACE((TUTRACE_NFC, "Pase WPS PW: Fail to allocate " "vendor extension buffer, Out of memory\n")); ret = WPS_ERR_OUTOFMEMORY; goto error; } buffobj_dserial(vendorExt_bufObj, vendorExt.vendorData, vendorExt.dataLength); /* Get Version2 subelement */ if ((buffobj_NextSubId(vendorExt_bufObj) != WPS_WFA_SUBID_VERSION2) || (subtlv_dserialize(&version2, WPS_WFA_SUBID_VERSION2, vendorExt_bufObj, 0, 0) != 0)) { TUTRACE((TUTRACE_NFC, "Pase WPS PW: Cannot get Version2\n")); /* ret = RPROT_ERR_INCOMPATIBLE; */ goto error; } if (version2.m_data < WPS_VERSION2) { TUTRACE((TUTRACE_NFC, "Pase WPS PW: Invalid Version2 number\n")); ret = RPROT_ERR_INCOMPATIBLE; goto error; } } error: /* free local alloc pointers */ if (vendorExt_bufObj) buffobj_del(vendorExt_bufObj); if (p_oobDevPwd) free(p_oobDevPwd); if (bufObj) buffobj_del(bufObj); return ret; }
uint32 nfc_utils_parse_cfg(WpsEnrCred *cred, uint8 wsp_version2, uint8 *buf, uint buflen) { uint32 ret = WPS_SUCCESS; char *cp_data; uint16 data16; BufferObj *bufObj = NULL; BufferObj *vendorExt_bufObj = NULL; CTlvVersion version; CSubTlvVersion2 version2; CTlvVendorExt vendorExt; CTlvCredential *p_tlvCred = NULL; /* Sanity check */ if (cred == NULL || buf == NULL || buflen == 0) { TUTRACE((TUTRACE_NFC, "Pase WPS CFG: Invalid parameters!\n")); ret = WPS_ERR_INVALID_PARAMETERS; goto error; } if (buflen < 7) { TUTRACE((TUTRACE_NFC, "Pase WPS CFG: buf length too short!\n")); ret = WPS_ERR_INVALID_PARAMETERS; goto error; } if (buf[5] != 0x10 || buf[6] != 0x0E) { TUTRACE((TUTRACE_NFC, "Pase WPS CFG: Not a Configuration Token!\n")); ret = WPS_ERR_INVALID_PARAMETERS; goto error; } /* Dserial raw data to bufObj */ bufObj = buffobj_new(); if (bufObj == NULL) { TUTRACE((TUTRACE_NFC, "Pase WPS CFG: Malloc fail!\n")); ret = WPS_ERR_OUTOFMEMORY; goto error; } WPS_HexDumpAscii("NFC_UTILS_PARSE_CFG", -1, buf, buflen); buffobj_dserial(bufObj, buf, buflen); /* Version 1 */ if (tlv_dserialize(&version, WPS_ID_VERSION, bufObj, 0, 0) != 0) { TUTRACE((TUTRACE_NFC, "Pase WPS CFG: TLV missing\n")); ret = RPROT_ERR_REQD_TLV_MISSING; goto error; } /* Must be 0x10, See WSC2.0 Clause 7.9 Version Negotiation */ if (version.m_data != WPS_VERSION) { TUTRACE((TUTRACE_NFC, "Pase WPS CFG: Message version should always set to 1\n")); ret = RPROT_ERR_INCOMPATIBLE; goto error; } /* Configuration */ /* Parse Credential */ p_tlvCred = (CTlvCredential *)malloc(sizeof(CTlvCredential)); if (!p_tlvCred) { TUTRACE((TUTRACE_NFC, "Pase WPS CFG: Malloc fail!\n")); ret = WPS_ERR_OUTOFMEMORY; goto error; } memset(p_tlvCred, 0, sizeof(CTlvCredential)); tlv_credentialParse(p_tlvCred, bufObj, true); /* Save CTlvCredential to WpsEnrCred */ /* Fill in SSID */ cp_data = (char *)(p_tlvCred->ssid.m_data); data16 = cred->ssidLen = p_tlvCred->ssid.tlvbase.m_len; strncpy(cred->ssid, cp_data, data16); cred->ssid[data16] = '\0'; /* Fill in keyMgmt */ if (p_tlvCred->authType.m_data == WPS_AUTHTYPE_SHARED) { strncpy(cred->keyMgmt, "SHARED", 6); cred->keyMgmt[6] = '\0'; } else if (p_tlvCred->authType.m_data == WPS_AUTHTYPE_WPAPSK) { strncpy(cred->keyMgmt, "WPA-PSK", 7); cred->keyMgmt[7] = '\0'; } else if (p_tlvCred->authType.m_data == WPS_AUTHTYPE_WPA2PSK) { strncpy(cred->keyMgmt, "WPA2-PSK", 8); cred->keyMgmt[8] = '\0'; } else if (p_tlvCred->authType.m_data == (WPS_AUTHTYPE_WPAPSK | WPS_AUTHTYPE_WPA2PSK)) { strncpy(cred->keyMgmt, "WPA-PSK WPA2-PSK", 16); cred->keyMgmt[16] = '\0'; } else { strncpy(cred->keyMgmt, "OPEN", 4); cred->keyMgmt[4] = '\0'; } /* get the real cypher */ cred->encrType = p_tlvCred->encrType.m_data; /* Fill in WEP index, no matter it's WEP type or not */ cred->wepIndex = p_tlvCred->WEPKeyIndex.m_data; /* Fill in PSK */ data16 = p_tlvCred->nwKey.tlvbase.m_len; memset(cred->nwKey, 0, SIZE_64_BYTES); memcpy(cred->nwKey, p_tlvCred->nwKey.m_data, data16); /* we have to set key length here */ cred->nwKeyLen = data16; /* WSC 2.0, nwKeyShareable */ cred->nwKeyShareable = p_tlvCred->nwKeyShareable.m_data; /* Version2, here you don't is peer WSC 2.0 or not */ if (wsp_version2 >= WPS_VERSION2) { if (tlv_find_vendorExtParse(&vendorExt, bufObj, (uint8 *)WFA_VENDOR_EXT_ID) != 0) { TUTRACE((TUTRACE_NFC, "Pase WPS CFG: Cannot find vendor extension\n")); /* ret = RPROT_ERR_INCOMPATIBLE; */ goto error; } /* Deserialize subelement */ if ((vendorExt_bufObj = buffobj_new()) == NULL) { TUTRACE((TUTRACE_NFC, "Pase WPS CFG: Fail to allocate " "vendor extension buffer, Out of memory\n")); ret = WPS_ERR_OUTOFMEMORY; goto error; } buffobj_dserial(vendorExt_bufObj, vendorExt.vendorData, vendorExt.dataLength); /* Get Version2 subelement */ if ((buffobj_NextSubId(vendorExt_bufObj) != WPS_WFA_SUBID_VERSION2) || (subtlv_dserialize(&version2, WPS_WFA_SUBID_VERSION2, vendorExt_bufObj, 0, 0) != 0)) { TUTRACE((TUTRACE_NFC, "Pase WPS CFG: Cannot get Version2\n")); /* ret = RPROT_ERR_INCOMPATIBLE; */ goto error; } if (version2.m_data < WPS_VERSION2) { TUTRACE((TUTRACE_NFC, "Pase WPS NDEF: Invalid Version2 number\n")); ret = RPROT_ERR_INCOMPATIBLE; goto error; } } error: /* free local alloc pointers */ if (vendorExt_bufObj) buffobj_del(vendorExt_bufObj); if (p_tlvCred) tlv_credentialDelete(p_tlvCred, 0); if (bufObj) buffobj_del(bufObj); return ret; }
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; }
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; }