Skip to content

Commit

Permalink
Miscellaneous bug fixes and GC allocation fixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
KillaMaaki committed Nov 1, 2017
1 parent f2b060e commit 744e244
Show file tree
Hide file tree
Showing 10 changed files with 485 additions and 189 deletions.
6 changes: 4 additions & 2 deletions BCCrypto/BCCrypto.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,14 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
Expand Down Expand Up @@ -1519,6 +1518,9 @@
<Compile Include="src\x509\X509V3CertificateGenerator.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>copy /Y "$(TargetDir)$(TargetFileName)" "$(SolutionDir)..\NeonUnityClient\Assets\Neon\Plugins\$(TargetFileName)"</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
Expand Down
23 changes: 21 additions & 2 deletions BCCrypto/src/crypto/parameters/KeyParameter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Org.BouncyCastle.Utilities;

using Org.BouncyCastle.Crypto;

Expand All @@ -7,7 +8,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
public class KeyParameter
: ICipherParameters
{
private readonly byte[] key;
private byte[] key;

public KeyParameter(
byte[] key)
Expand Down Expand Up @@ -36,7 +37,25 @@ public class KeyParameter

public byte[] GetKey()
{
return (byte[]) key.Clone();
//return (byte[]) key.Clone();
return key;
}

public void Reset()
{
BufferPool.ReturnBuffer(this.key);
this.key = null;
}

public void SetKey( byte[] key )
{
SetKey(key, 0, key.Length);
}

public void SetKey(byte[] key, int keyoff, int keylen)
{
this.key = BufferPool.GetBuffer(keylen);
Array.Copy(key, keyoff, this.key, 0, keylen);
}
}

Expand Down
21 changes: 18 additions & 3 deletions BCCrypto/src/crypto/parameters/ParametersWithIV.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using System;
using Org.BouncyCastle.Utilities;

namespace Org.BouncyCastle.Crypto.Parameters
{
public class ParametersWithIV
: ICipherParameters
{
private readonly ICipherParameters parameters;
private readonly byte[] iv;
private ICipherParameters parameters;
private byte[] iv;

public ParametersWithIV(
ICipherParameters parameters,
Expand All @@ -30,9 +31,23 @@ public class ParametersWithIV
Array.Copy(iv, ivOff, this.iv, 0, ivLen);
}

public void Set( ICipherParameters parameters, byte[] iv )
{
this.parameters = parameters;
this.iv = BufferPool.GetBuffer(iv.Length);
Array.Copy(iv, 0, this.iv, 0, this.iv.Length);
}

public void Reset()
{
BufferPool.ReturnBuffer(this.iv);
this.iv = null;
}

public byte[] GetIV()
{
return (byte[]) iv.Clone();
//return (byte[]) iv.Clone();
return iv;
}

public ICipherParameters Parameters
Expand Down
169 changes: 110 additions & 59 deletions BCCrypto/src/crypto/tls/AEAD_Chacha20_Poly1305.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,84 +13,135 @@ namespace Org.BouncyCastle.Crypto.TlsExt
public class AEAD_Chacha20_Poly1305
{
private static readonly byte[] Zeroes = new byte[15];
private static ChaCha7539Engine cipher;

public static int Encrypt(byte[] plaintext, int offset, int len, byte[] additionalData, byte[] nonce, byte[] key, byte[] outBuffer)
{
var cipher = new ChaCha7539Engine();

var encryptKey = new KeyParameter(key);
cipher.Init(true, new ParametersWithIV(encryptKey, nonce));
private static IMac _mac = new Poly1305();

byte[] firstBlock = BufferPool.GetBuffer(64);
KeyParameter macKey = GenerateRecordMacKey(cipher, firstBlock);
cipher.ProcessBytes(plaintext, offset, len, outBuffer, 0);
private static ParametersWithIV _temp_Params;
private static KeyParameter _encryptKey;
private static KeyParameter _decryptKey;
private static KeyParameter _macKey;

byte[] mac = BufferPool.GetBuffer(16);
int macsize = CalculateRecordMac(macKey, additionalData, outBuffer, 0, len, mac);
Array.Copy(mac, 0, outBuffer, len, macsize);
private static object mutex = new object();

BufferPool.ReturnBuffer(mac);
BufferPool.ReturnBuffer(firstBlock);

return len + 16;
public static int Encrypt(byte[] plaintext, int offset, int len, byte[] additionalData, byte[] nonce, byte[] key, byte[] outBuffer)
{
lock (mutex) {
if (cipher == null)
cipher = new ChaCha7539Engine();
else
cipher.Reset();

if (_encryptKey == null)
_encryptKey = new KeyParameter(key);
else {
_encryptKey.Reset();
_encryptKey.SetKey(key);
}

if (_temp_Params == null)
_temp_Params = new ParametersWithIV(_encryptKey, nonce);
else {
_temp_Params.Reset();
_temp_Params.Set(_encryptKey, nonce);
}

cipher.Init(true, _temp_Params);

byte[] firstBlock = BufferPool.GetBuffer(64);
KeyParameter macKey = GenerateRecordMacKey(cipher, firstBlock);

cipher.ProcessBytes(plaintext, offset, len, outBuffer, 0);

byte[] mac = BufferPool.GetBuffer(16);
int macsize = CalculateRecordMac(macKey, additionalData, outBuffer, 0, len, mac);
Array.Copy(mac, 0, outBuffer, len, macsize);

BufferPool.ReturnBuffer(mac);
BufferPool.ReturnBuffer(firstBlock);

return len + 16;
}
}

public static int Decrypt(byte[] ciphertext, int offset, int len, byte[] additionalData, byte[] nonce, byte[] key, byte[] outBuffer)
{
var cipher = new ChaCha7539Engine();

var decryptKey = new KeyParameter(key);
cipher.Init(false, new ParametersWithIV(decryptKey, nonce));

byte[] firstBlock = BufferPool.GetBuffer(64);
KeyParameter macKey = GenerateRecordMacKey(cipher, firstBlock);

int plaintextLength = len - 16;

byte[] calculatedMac = BufferPool.GetBuffer(16);
CalculateRecordMac(macKey, additionalData, ciphertext, offset, plaintextLength, calculatedMac);

byte[] receivedMac = BufferPool.GetBuffer(16);
Array.Copy(ciphertext, offset + plaintextLength, receivedMac, 0, receivedMac.Length);

if (!Arrays.ConstantTimeAreEqual(calculatedMac, receivedMac))
{
BufferPool.ReturnBuffer(calculatedMac);
BufferPool.ReturnBuffer(receivedMac);
BufferPool.ReturnBuffer(firstBlock);

throw new TlsFatalAlert(AlertDescription.bad_record_mac);
}

BufferPool.ReturnBuffer(calculatedMac);
BufferPool.ReturnBuffer(receivedMac);
BufferPool.ReturnBuffer(firstBlock);

cipher.ProcessBytes(ciphertext, offset, plaintextLength, outBuffer, 0);
return plaintextLength;
lock (mutex) {
if (cipher == null)
cipher = new ChaCha7539Engine();
else
cipher.Reset();

if (_decryptKey == null)
_decryptKey = new KeyParameter(key);
else {
_decryptKey.Reset();
_decryptKey.SetKey(key);
}

if (_temp_Params == null)
_temp_Params = new ParametersWithIV(_decryptKey, nonce);
else {
_temp_Params.Reset();
_temp_Params.Set(_decryptKey, nonce);
}

cipher.Init(false, _temp_Params);

byte[] firstBlock = BufferPool.GetBuffer(64);
KeyParameter macKey = GenerateRecordMacKey(cipher, firstBlock);

int plaintextLength = len - 16;

byte[] calculatedMac = BufferPool.GetBuffer(16);
CalculateRecordMac(macKey, additionalData, ciphertext, offset, plaintextLength, calculatedMac);

byte[] receivedMac = BufferPool.GetBuffer(16);
Array.Copy(ciphertext, offset + plaintextLength, receivedMac, 0, receivedMac.Length);

if (!Arrays.ConstantTimeAreEqual(calculatedMac, receivedMac)) {
BufferPool.ReturnBuffer(calculatedMac);
BufferPool.ReturnBuffer(receivedMac);
BufferPool.ReturnBuffer(firstBlock);

throw new TlsFatalAlert(AlertDescription.bad_record_mac);
}

BufferPool.ReturnBuffer(calculatedMac);
BufferPool.ReturnBuffer(receivedMac);
BufferPool.ReturnBuffer(firstBlock);

cipher.ProcessBytes(ciphertext, offset, plaintextLength, outBuffer, 0);
return plaintextLength;
}
}

protected static KeyParameter GenerateRecordMacKey(IStreamCipher cipher, byte[] firstBlock)
{
cipher.ProcessBytes(firstBlock, 0, firstBlock.Length, firstBlock, 0);

KeyParameter macKey = new KeyParameter(firstBlock, 0, 32);
Arrays.Fill(firstBlock, (byte)0);
return macKey;

if (_macKey == null)
_macKey = new KeyParameter(firstBlock, 0, 32);
else {
_macKey.Reset();
_macKey.SetKey(firstBlock, 0, 32);
}

Arrays.Fill(firstBlock, (byte)0);
return _macKey;
}

protected static int CalculateRecordMac(KeyParameter macKey, byte[] additionalData, byte[] buf, int off, int len, byte[] outMac)
{
IMac mac = new Poly1305();
mac.Init(macKey);
_mac.Reset();
_mac.Init(macKey);

UpdateRecordMacText(mac, additionalData, 0, additionalData.Length);
UpdateRecordMacText(mac, buf, off, len);
UpdateRecordMacLength(mac, additionalData.Length);
UpdateRecordMacLength(mac, len);
UpdateRecordMacText(_mac, additionalData, 0, additionalData.Length);
UpdateRecordMacText(_mac, buf, off, len);
UpdateRecordMacLength(_mac, additionalData.Length);
UpdateRecordMacLength(_mac, len);

return MacUtilities.DoFinalOut(mac, outMac);
return MacUtilities.DoFinalOut(_mac, outMac);
}

protected static void UpdateRecordMacLength(IMac mac, int len)
Expand Down
2 changes: 1 addition & 1 deletion Netcode.IO.NET/Core/EncryptionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public bool RemoveEncryptionMapping(EndPoint address, double time)
int index = i - 1;
while (index >= 0)
{
if ((encryptionMappings[i].TimeoutSeconds < 0 || encryptionMappings[index].LastAccessTime + encryptionMappings[i].TimeoutSeconds >= time ) &&
if ((encryptionMappings[index].TimeoutSeconds < 0 || encryptionMappings[index].LastAccessTime + encryptionMappings[index].TimeoutSeconds >= time ) &&
(encryptionMappings[index].ExpireTime < 0 || encryptionMappings[index].ExpireTime > time))
break;
index--;
Expand Down
1 change: 1 addition & 0 deletions Netcode.IO.NET/Core/PacketIO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public static int ReadPacketData(NetcodePacketHeader header, ByteArrayReaderWrit
throw e;
}

BufferPool.ReturnBuffer(encryptedBuffer);
return decryptedBytes;
}

Expand Down
3 changes: 3 additions & 0 deletions Netcode.IO.NET/Netcode.IO.NET.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>copy /Y "$(TargetDir)$(TargetFileName)" "$(SolutionDir)..\NeonUnityClient\Assets\Neon\Plugins\$(TargetFileName)"</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
Expand Down
25 changes: 20 additions & 5 deletions Netcode.IO.NET/Public/Server.cs
Original file line number Diff line number Diff line change
Expand Up @@ -432,14 +432,18 @@ private void processDatagram(byte[] payload, int size, EndPoint sender)
private bool checkReplay(NetcodePacketHeader header, EndPoint sender)
{
var cryptIdx = encryptionManager.FindEncryptionMapping(sender, time);
if (cryptIdx == -1)
return true;
if (cryptIdx == -1) {
log("Replay protection failed to find encryption mapping", NetcodeLogLevel.Debug);
return true;
}

var clientIndex = encryptionManager.GetClientID(cryptIdx);
var client = clientSlots[clientIndex];

if (client == null)
return true;
if (client == null) {
log("Replay protection failed to find client", NetcodeLogLevel.Debug);
return true;
}

return client.replayProtection.AlreadyReceived(header.SequenceNumber);
}
Expand Down Expand Up @@ -477,6 +481,13 @@ private void processConnectionDisconnect(ByteArrayReaderWriter reader, NetcodePa
// remove encryption mapping
encryptionManager.RemoveEncryptionMapping(sender, time);

// make sure all other clients still have their encryption mappings
foreach (RemoteClient otherClient in clientSlots) {
if (otherClient == null) continue;
if (encryptionManager.FindEncryptionMapping(otherClient.RemoteEndpoint, time) == -1)
log("Encryption mapping removed wrong mapping!", NetcodeLogLevel.Debug);
}

// trigger client disconnect callback
if (OnClientDisconnected != null)
OnClientDisconnected(client);
Expand Down Expand Up @@ -522,6 +533,7 @@ private void processConnectionKeepAlive(ByteArrayReaderWriter reader, NetcodePac
{
if (checkReplay(header, sender))
{
log("Detected replay in keep-alive", NetcodeLogLevel.Debug);
return;
}

Expand Down Expand Up @@ -550,7 +562,10 @@ private void processConnectionKeepAlive(ByteArrayReaderWriter reader, NetcodePac
}

var client = this.clientSlots[(int)keepAlivePacket.ClientIndex];
if (client == null) return;
if (client == null) {
log("Failed to find client for endpoint", NetcodeLogLevel.Debug);
return;
}

if (!client.RemoteEndpoint.Equals(sender))
{
Expand Down
Loading

0 comments on commit 744e244

Please sign in to comment.