From 7dcb896f3d34c7ab1079b04f16beaf572c4770e3 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Fri, 25 Sep 2015 21:50:45 +0100 Subject: [PATCH] Rewrite BlowfishKeyProvider.ProcessPredata using safe code. Fixes #2441. This error would occur when the memory regions were allocated at particular addresses when running a mono-compiled binary on a .net runtime. The data would be copied to the pointer returned from a fixed() statement, but the managed array would *not* be updated with the new data. This caused DecryptKey to silently return a bogus key full of zeros, and the mix file header decryption would subsequently fail. --- .../FileFormats/BlowfishKeyProvider.cs | 45 +++++++------------ 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/OpenRA.Game/FileFormats/BlowfishKeyProvider.cs b/OpenRA.Game/FileFormats/BlowfishKeyProvider.cs index 306ac81dc5..a64a116ce9 100644 --- a/OpenRA.Game/FileFormats/BlowfishKeyProvider.cs +++ b/OpenRA.Game/FileFormats/BlowfishKeyProvider.cs @@ -119,12 +119,6 @@ namespace OpenRA.FileFormats pubkey.Len = BitLenBigNum(pubkey.KeyOne, 64) - 1; } - uint LenPreData() - { - var a = (pubkey.Len - 1) / 8; - return (55 / a + 1) * (a + 1); - } - static int CompareBigNum(uint[] n1, uint[] n2, uint len) { while (len > 0) @@ -462,46 +456,37 @@ namespace OpenRA.FileFormats } } - static unsafe void Memcopy(byte* dest, byte* src, int len) - { - while (len-- != 0) *dest++ = *src++; - } - - unsafe void ProcessPredata(byte* pre, uint pre_len, byte* buf) + byte[] ProcessPredata(byte[] src) { + var dest = new byte[256]; var n2 = new uint[64]; var n3 = new uint[64]; - var a = (pubkey.Len - 1) / 8; + var a = (int)((pubkey.Len - 1) / 8); + var pre_len = (55 / a + 1) * (a + 1); + var srcOffset = 0; + var destOffset = 0; + while (a + 1 <= pre_len) { InitBigNum(n2, 0, 64); - fixed (uint* pn2 = &n2[0]) - Memcopy((byte*)pn2, pre, (int)a + 1); - CalcKey(n3, n2, pubkey.KeyTwo, pubkey.KeyOne, 64); - fixed (uint* pn3 = &n3[0]) - Memcopy(buf, (byte*)pn3, (int)a); + Buffer.BlockCopy(src, srcOffset, n2, 0, a + 1); + CalcKey(n3, n2, pubkey.KeyTwo, pubkey.KeyOne, 64); + Buffer.BlockCopy(n3, 0, dest, destOffset, a); pre_len -= a + 1; - pre += a + 1; - buf += a; + srcOffset += a + 1; + destOffset += a; } + + return dest; } public byte[] DecryptKey(byte[] src) { InitPublicKey(); - var dest = new byte[256]; - - unsafe - { - fixed (byte* pdest = &dest[0]) - fixed (byte* psrc = &src[0]) - ProcessPredata(psrc, LenPreData(), pdest); - } - - return dest.Take(56).ToArray(); + return ProcessPredata(src).Take(56).ToArray(); } } }