BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, UINT16* pLength, UINT16 securityFlags)
{
	BYTE cmac[8];
	BYTE wmac[8];
	BOOL status;
	INT32 length;

	if (!rdp || !s || !pLength)
		return FALSE;

	length = *pLength;
	if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
	{
		UINT16 len;
		BYTE version, pad;
		BYTE* sig;
		INT64 padLength;

		if (Stream_GetRemainingLength(s) < 12)
			return FALSE;

		Stream_Read_UINT16(s, len);    /* 0x10 */
		Stream_Read_UINT8(s, version); /* 0x1 */
		Stream_Read_UINT8(s, pad);
		sig = Stream_Pointer(s);
		Stream_Seek(s, 8); /* signature */
		length -= 12;
		padLength = length - pad;

		if ((length <= 0) || (padLength <= 0))
			return FALSE;

		if (!security_fips_decrypt(Stream_Pointer(s), length, rdp))
		{
			WLog_ERR(TAG, "FATAL: cannot decrypt");
			return FALSE; /* TODO */
		}

		if (!security_fips_check_signature(Stream_Pointer(s), length - pad, sig, rdp))
		{
			WLog_ERR(TAG, "FATAL: invalid packet signature");
			return FALSE; /* TODO */
		}

		Stream_SetLength(s, Stream_Length(s) - pad);
		*pLength = padLength;
		return TRUE;
	}

	if (Stream_GetRemainingLength(s) < sizeof(wmac))
		return FALSE;

	Stream_Read(s, wmac, sizeof(wmac));
	length -= sizeof(wmac);

	if (length <= 0)
		return FALSE;

	if (!security_decrypt(Stream_Pointer(s), length, rdp))
		return FALSE;

	if (securityFlags & SEC_SECURE_CHECKSUM)
		status = security_salted_mac_signature(rdp, Stream_Pointer(s), length, FALSE, cmac);
	else
		status = security_mac_signature(rdp, Stream_Pointer(s), length, cmac);

	if (!status)
		return FALSE;

	if (memcmp(wmac, cmac, sizeof(wmac)) != 0)
	{
		WLog_ERR(TAG, "WARNING: invalid packet signature");
		/*
		 * Because Standard RDP Security is totally broken,
		 * and cannot protect against MITM, don't treat signature
		 * verification failure as critical. This at least enables
		 * us to work with broken RDP clients and servers that
		 * generate invalid signatures.
		 */
		// return FALSE;
	}

	*pLength = length;
	return TRUE;
}
BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, UINT16* pLength, UINT16 securityFlags)
{
	BYTE cmac[8];
	BYTE wmac[8];
	BOOL status;
	INT32 length;

	if (!rdp || !s || !pLength)
		return FALSE;

	length = *pLength;
	if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
	{
		UINT16 len;
		BYTE version, pad;
		BYTE* sig;
		INT64 padLength;

		if (Stream_GetRemainingLength(s) < 12)
			return FALSE;

		Stream_Read_UINT16(s, len);     
		Stream_Read_UINT8(s, version);  
		Stream_Read_UINT8(s, pad);
		sig = Stream_Pointer(s);
		Stream_Seek(s, 8);  
		length -= 12;
		padLength = length - pad;

		if ((length <= 0) || (padLength <= 0))
			return FALSE;

		if (!security_fips_decrypt(Stream_Pointer(s), length, rdp))
		{
			WLog_ERR(TAG, "FATAL: cannot decrypt");
			return FALSE;  
		}

		if (!security_fips_check_signature(Stream_Pointer(s), length - pad, sig, rdp))
		{
			WLog_ERR(TAG, "FATAL: invalid packet signature");
			return FALSE;  
		}

		Stream_SetLength(s, Stream_Length(s) - pad);
		*pLength = padLength;
		return TRUE;
	}

	if (Stream_GetRemainingLength(s) < sizeof(wmac))
		return FALSE;

	Stream_Read(s, wmac, sizeof(wmac));
	length -= sizeof(wmac);

	if (length <= 0)
		return FALSE;

	if (!security_decrypt(Stream_Pointer(s), length, rdp))
		return FALSE;

	if (securityFlags & SEC_SECURE_CHECKSUM)
		status = security_salted_mac_signature(rdp, Stream_Pointer(s), length, FALSE, cmac);
	else
		status = security_mac_signature(rdp, Stream_Pointer(s), length, cmac);

	if (!status)
		return FALSE;

	if (memcmp(wmac, cmac, sizeof(wmac)) != 0)
	{
		WLog_ERR(TAG, "WARNING: invalid packet signature");
		 
		 
	}

	*pLength = length;
	return TRUE;
}