In non-AES mode, we now replace packets whose hash starts with
FFFFFFFF by
7FFFFFFF, and 8000LLLL by 0000LLLL. When decoding, packets with these prefixes
have two attempts.
AES encrypted mode is unaffected by this, as there packets always start with a
byte from 00 to 0F.
Also, no longer whine about receiving packets that fail the HMAC test when the
packets look like control packets (the NQ CONNECT packet DP sends when
connecting sometimes was received in time for this to match).
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11068
d7cf8633-e32d-0410-b094-
e92efae38249
+// NOTE: we MUST avoid the following begins of the packet:
+// 1. 0xFF, 0xFF, 0xFF, 0xFF
+// 2. 0x80, 0x00, length/256, length%256
+// this luckily does NOT affect AES mode, where the first byte always is in the range from 0x00 to 0x0F
const void *Crypto_EncryptPacket(crypto_t *crypto, const void *data_src, size_t len_src, void *data_dst, size_t *len_dst, size_t len)
{
unsigned char h[32];
const void *Crypto_EncryptPacket(crypto_t *crypto, const void *data_src, size_t len_src, void *data_dst, size_t *len_dst, size_t len)
{
unsigned char h[32];
if(crypto->authenticated)
{
if(crypto->use_aes)
if(crypto->authenticated)
{
if(crypto->use_aes)
*len_dst = len_src + 16;
memcpy(data_dst, h, 16);
memcpy(((unsigned char *) data_dst) + 16, (unsigned char *) data_src, len_src);
*len_dst = len_src + 16;
memcpy(data_dst, h, 16);
memcpy(((unsigned char *) data_dst) + 16, (unsigned char *) data_src, len_src);
+
+ // handle the "avoid" conditions:
+ i = BuffBigLong(data_dst);
+ if(
+ (i == (int)0xFFFFFFFF) // avoid QW control packet
+ ||
+ (i == (int)0x80000000 + (int)*len_dst) // avoid NQ control packet
+ )
+ *(unsigned char *)data_dst ^= 0x80; // this will ALWAYS fix it
const void *Crypto_DecryptPacket(crypto_t *crypto, const void *data_src, size_t len_src, void *data_dst, size_t *len_dst, size_t len)
{
unsigned char h[32];
const void *Crypto_DecryptPacket(crypto_t *crypto, const void *data_src, size_t len_src, void *data_dst, size_t *len_dst, size_t len)
{
unsigned char h[32];
+ int i;
+
+ // silently handle non-crypto packets
+ i = BuffBigLong(data_src);
+ if(
+ (i == (int)0xFFFFFFFF) // avoid QW control packet
+ ||
+ (i == (int)0x80000000 + (int)len_src) // avoid NQ control packet
+ )
+ return NULL;
+
if(crypto->authenticated)
{
if(crypto->use_aes)
if(crypto->authenticated)
{
if(crypto->use_aes)
Com_HexDumpToConsole((const unsigned char *) data_src, len_src);
return NULL;
}
Com_HexDumpToConsole((const unsigned char *) data_src, len_src);
return NULL;
}
if(memcmp((const unsigned char *) data_src, h, 16)) // ignore first byte, used for length
{
if(memcmp((const unsigned char *) data_src, h, 16)) // ignore first byte, used for length
{
- Con_Printf("HMAC mismatch\n");
- Com_HexDumpToConsole((const unsigned char *) data_src, len_src);
- return NULL;
+ // undo the "avoid conditions"
+ if(
+ (i == (int)0x7FFFFFFF) // avoided QW control packet
+ ||
+ (i == (int)0x00000000 + (int)len_src) // avoided NQ control packet
+ )
+ {
+ // do the avoidance on the hash too
+ h[0] ^= 0x80;
+ if(memcmp((const unsigned char *) data_src, h, 16)) // ignore first byte, used for length
+ {
+ Con_Printf("HMAC mismatch\n");
+ Com_HexDumpToConsole((const unsigned char *) data_src, len_src);
+ return NULL;
+ }
+ }
+ else
+ {
+ Con_Printf("HMAC mismatch\n");
+ Com_HexDumpToConsole((const unsigned char *) data_src, len_src);
+ return NULL;
+ }
}
return ((const unsigned char *) data_src) + 16; // no need to copy, so data_dst is not used
}
}
return ((const unsigned char *) data_src) + 16; // no need to copy, so data_dst is not used
}