//Encrypted settings for M7
//ES when M7 is from an enrollee
void CTlvEsM7Enr::parse(BufferObj &theBuf, BufferObj &authKey, bool allocate)
{
    nonce = CTlvNonce(WSC_ID_E_SNONCE2, theBuf, SIZE_128_BITS);

    if(WSC_ID_IDENTITY_PROOF == theBuf.NextType())
        idProof = CTlvIdentityProof(WSC_ID_IDENTITY_PROOF, theBuf, 0, allocate);

	// Skip attributes until the KeyWrapAuthenticator
	while(WSC_ID_KEY_WRAP_AUTH != theBuf.NextType())
    {
        //advance past the TLV
        uint8 *Pos = theBuf.Advance( sizeof(S_WSC_TLV_HEADER) + 
							WscNtohs(*(uint16 *)(theBuf.Pos()+sizeof(uint16))) );
        
        //If Advance returned NULL, it means there's no more data in the
        //buffer. This is an error.
        if(Pos == NULL)
            throw RPROT_ERR_REQD_TLV_MISSING;
    }

	uint8 * startOfAuthenticator = theBuf.Pos();
    keyWrapAuth = CTlvAuthenticator(WSC_ID_KEY_WRAP_AUTH, theBuf, SIZE_64_BITS);

    //validate the mac
    uint8 dataMac[BUF_SIZE_256_BITS];

    //calculate the hmac of the data (data only, not the last auth TLV)
    if(HMAC(EVP_sha256(), authKey.GetBuf(), SIZE_256_BITS, theBuf.GetBuf(),
            startOfAuthenticator - theBuf.GetBuf(), 
            dataMac, NULL) == NULL)
    {
        TUTRACE((TUTRACE_ERR, "RPROTO: HMAC failed\n"));
        throw RPROT_ERR_CRYPTO;
    }

    //compare it against the received hmac
    if(memcmp(dataMac, keyWrapAuth.Value(), SIZE_64_BITS) != 0)
    {
        TUTRACE((TUTRACE_ERR, "RPROTO: HMAC results don't match\n"));
        throw RPROT_ERR_INVALID_VALUE;
    }
}
int WPSRegistrar::ProcessDone()
{
	uint32 err;

	err = g_regProtocol.ProcessMessageDone(&m_regInfo, m_msgBuffer );
    if(WSC_SUCCESS != err)
    {
		return err_process_Done;
    }
	printf("\n*****  Successfully processed Message Done\n");
	if (m_regInfo.p_enrolleeInfo) {
		WPSDeviceWasAuthenticated(* ((GUID*) & (m_regInfo.p_enrolleeInfo->uuid)));
	}

	//****** Derivation of UPnP Protected Setup AuthKey and KeyWrapKey ******
    //1. declare and initialize the appropriate buffer objects
	BufferObj kdkBuf(m_regInfo.emsk.GetBuf(), SIZE_256_BITS);
    BufferObj pString((uint8 *)UPNP_PERSONALIZATION_STRING, 
                        strlen(UPNP_PERSONALIZATION_STRING));
    BufferObj keys;

    //2. call the key derivation function
    g_regProtocol.DeriveKey(kdkBuf, pString, 256 + 128, keys);

    //3. split the key into the component keys and store them
    keys.Rewind(keys.Length());
    m_regInfo.UPnPPSauthKey.Reset();
	m_regInfo.UPnPPSkeyWrapKey.Reset();

	m_regInfo.UPnPPSauthKey.Append(SIZE_256_BITS, keys.Pos());
    keys.Advance(SIZE_256_BITS);

    m_regInfo.UPnPPSkeyWrapKey.Append(SIZE_128_BITS, keys.Pos());
	// **** End of key derivation code

	return init;
}
void CTlvEsM8Sta::writeGenericCredentials(BufferObj &theBuf)
{
    LPLISTITR itr;
    CTlvCredential *pCredential;

    //there should be at least one credential TLV
    if(0 == ListGetCount(credential))
        throw RPROT_ERR_REQD_TLV_MISSING;

    try
    {
        if(!(itr = ListItrCreate(credential)))
            throw WSC_ERR_OUTOFMEMORY;

		uint8   macAddr[SIZE_6_BYTES];
		memset(macAddr,0,sizeof(macAddr));

        while((pCredential = (CTlvCredential *)ListItrGetNext(itr)))
        {
			uint8 * pos = theBuf.Pos(); // pos will point prior to Credential 
            pCredential->write(theBuf); // write out the Credential data
			theBuf.Set(pos);			// rewind prior to Credential
			CTlvCredential cr;			// local Credential to override MAC address pointer
			cr.parse(theBuf);			// create copy of Credential from buffer
			cr.macAddr.Set( WSC_ID_MAC_ADDR, macAddr, SIZE_6_BYTES );
			theBuf.Set(pos);
			cr.write(theBuf);			// overwrite the data in the buffer
		}

        ListItrDelete(itr);  
    }
    catch(...)
    {
        if(itr)
            ListItrDelete(itr);
    }
}
void CTlvEsM8Sta::parse(BufferObj &theBuf, BufferObj &authKey, bool allocate, bool isWirelessWPS)
{
    //There should be at least 1 credential TLV
    CTlvCredential *pCredential;

	if (isWirelessWPS) { // Credential(s) are processed only when doing wireless WPS
		pCredential = new CTlvCredential();
		pCredential->parse(theBuf, allocate);
		ListAddItem(credential, pCredential);

		//now parse any additional credential TLVs
		while(WSC_ID_CREDENTIAL == theBuf.NextType())
		{
			pCredential = new CTlvCredential();
			pCredential->parse(theBuf, allocate);
			ListAddItem(credential, pCredential);
		}
	} 
	// Note that all Credentials are ignored if not doing wireless WPS.  Also, if a Credential
	// is present in this case, then the new password attribute will be ignored as well, because 
	// the Credential attribute will be next to be parsed in the message, which will cause the code 
	// to drop down to just skipping all attributes until the key wrap authenticator.

    if(WSC_ID_NEW_PWD == theBuf.NextType())
    {
       //If the New Password TLV is included, the Device password ID is required
        new_pwd = CTlvNewPwd(WSC_ID_NEW_PWD, theBuf, SIZE_64_BYTES, allocate);
        pwdId = CTlvDevicePwdId(WSC_ID_DEVICE_PWD_ID, theBuf);
    }

	// Skip attributes until the KeyWrapAuthenticator
	while(WSC_ID_KEY_WRAP_AUTH != theBuf.NextType())
    {
        //advance past the TLV
        uint8 *Pos = theBuf.Advance( sizeof(S_WSC_TLV_HEADER) + 
							WscNtohs(*(uint16 *)(theBuf.Pos()+sizeof(uint16))) );
        
        //If Advance returned NULL, it means there's no more data in the
        //buffer. This is an error.
        if(Pos == NULL)
            throw RPROT_ERR_REQD_TLV_MISSING;
    }

	uint8 * startOfAuthenticator = theBuf.Pos();
    keyWrapAuth = CTlvAuthenticator(WSC_ID_KEY_WRAP_AUTH, theBuf, SIZE_64_BITS);

    //validate the mac
    uint8 dataMac[BUF_SIZE_256_BITS];

    //calculate the hmac of the data (data only, not the last auth TLV)
    if(HMAC(EVP_sha256(), authKey.GetBuf(), SIZE_256_BITS, theBuf.GetBuf(),
            startOfAuthenticator - theBuf.GetBuf(), 
            dataMac, NULL) == NULL)
    {
        TUTRACE((TUTRACE_ERR, "RPROTO: HMAC failed\n"));
        throw RPROT_ERR_CRYPTO;
    }

    //compare it against the received hmac
    if(memcmp(dataMac, keyWrapAuth.Value(), SIZE_64_BITS) != 0)
    {
        TUTRACE((TUTRACE_ERR, "RPROTO: HMAC results don't match\n"));
        throw RPROT_ERR_INVALID_VALUE;
    }
}
void CTlvEsM8Ap::parse(BufferObj &theBuf, BufferObj &authKey, bool allocate)
{
    CTlvNwKeyIndex  *keyIndex;
    CTlvNwKey        *key;

    //NW Index is optional
    if(WSC_ID_NW_INDEX == theBuf.NextType())
        nwIndex = CTlvNwIndex(WSC_ID_NW_INDEX, theBuf);

    ssid  = CTlvSsid(WSC_ID_SSID, theBuf, SIZE_32_BYTES, allocate);
    authType = CTlvAuthType(WSC_ID_AUTH_TYPE, theBuf);
    encrType = CTlvEncrType(WSC_ID_ENCR_TYPE, theBuf);
   
    //The next field is network key index. There are two possibilities:
    //1. The TLV is omitted, in which case, there is only 1 network key
    //2. The TLV is present, in which case, there may be 1 or more network keys
    
    //condition 1. If the next field is a network Key, the index TLV was omitted
    if(WSC_ID_NW_KEY == theBuf.NextType())
    {
        key = new CTlvNwKey(WSC_ID_NW_KEY, theBuf, SIZE_64_BYTES, allocate);
        if(!key)
            throw WSC_ERR_OUTOFMEMORY;
        ListAddItem(nwKey, key);
    }
    else
    {
        //condition 2. any other possibities are illegal & will be caught later
        while(WSC_ID_NW_KEY_INDEX == theBuf.NextType())
        {
            keyIndex = new CTlvNwKeyIndex(WSC_ID_NW_KEY_INDEX, theBuf);
            if(!keyIndex)
                throw WSC_ERR_OUTOFMEMORY;
            ListAddItem(nwKeyIndex, keyIndex);

            key = new CTlvNwKey(WSC_ID_NW_KEY, theBuf, SIZE_64_BYTES, allocate);
            if(!key)
                throw WSC_ERR_OUTOFMEMORY;
            ListAddItem(nwKey, key);
        }//while
    }//else

    macAddr = CTlvMacAddr(WSC_ID_MAC_ADDR, theBuf, SIZE_6_BYTES, allocate);

    if(WSC_ID_NEW_PWD == theBuf.NextType())
    {
       //If the New Password TLV is included, the Device password ID is required
        new_pwd = CTlvNewPwd(WSC_ID_NEW_PWD, theBuf, SIZE_64_BYTES, allocate);
        pwdId = CTlvDevicePwdId(WSC_ID_DEVICE_PWD_ID, theBuf);
    }

    //skip Permitted Config Methods field.
    if(WSC_ID_PERM_CFG_METHODS == theBuf.NextType())
    {
        //advance past the TLV
        theBuf.Advance( sizeof(S_WSC_TLV_HEADER) + 
                        WscNtohs(*(uint16 *)(theBuf.Pos()+sizeof(uint16))) );
    }

	// Skip attributes until the KeyWrapAuthenticator
	while(WSC_ID_KEY_WRAP_AUTH != theBuf.NextType())
    {
        //advance past the TLV
        uint8 *Pos = theBuf.Advance( sizeof(S_WSC_TLV_HEADER) + 
							WscNtohs(*(uint16 *)(theBuf.Pos()+sizeof(uint16))) );
        
        //If Advance returned NULL, it means there's no more data in the
        //buffer. This is an error.
        if(Pos == NULL)
            throw RPROT_ERR_REQD_TLV_MISSING;
    }

	uint8 * startOfAuthenticator = theBuf.Pos();
    keyWrapAuth = CTlvAuthenticator(WSC_ID_KEY_WRAP_AUTH, theBuf, SIZE_64_BITS);

    //validate the mac
    uint8 dataMac[BUF_SIZE_256_BITS];

    //calculate the hmac of the data (data only, not the last auth TLV)
    if(HMAC(EVP_sha256(), authKey.GetBuf(), SIZE_256_BITS, theBuf.GetBuf(),
            startOfAuthenticator - theBuf.GetBuf(), 
            dataMac, NULL) == NULL)
    {
        TUTRACE((TUTRACE_ERR, "RPROTO: HMAC failed\n"));
        throw RPROT_ERR_CRYPTO;
    }

    //compare it against the received hmac
    if(memcmp(dataMac, keyWrapAuth.Value(), SIZE_64_BITS) != 0)
    {
        TUTRACE((TUTRACE_ERR, "RPROTO: HMAC results don't match\n"));
        throw RPROT_ERR_INVALID_VALUE;
    }
}