//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;
    }
}
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;
    }
}