init commit
This commit is contained in:
@@ -0,0 +1,294 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Tls;
|
||||
|
||||
public class TlsBlockCipher : TlsCipher
|
||||
{
|
||||
protected readonly TlsContext context;
|
||||
|
||||
protected readonly byte[] randomData;
|
||||
|
||||
protected readonly bool useExplicitIV;
|
||||
|
||||
protected readonly bool encryptThenMac;
|
||||
|
||||
protected readonly IBlockCipher encryptCipher;
|
||||
|
||||
protected readonly IBlockCipher decryptCipher;
|
||||
|
||||
protected readonly TlsMac mWriteMac;
|
||||
|
||||
protected readonly TlsMac mReadMac;
|
||||
|
||||
public virtual TlsMac WriteMac => mWriteMac;
|
||||
|
||||
public virtual TlsMac ReadMac => mReadMac;
|
||||
|
||||
public TlsBlockCipher(TlsContext context, IBlockCipher clientWriteCipher, IBlockCipher serverWriteCipher, IDigest clientWriteDigest, IDigest serverWriteDigest, int cipherKeySize)
|
||||
{
|
||||
this.context = context;
|
||||
randomData = new byte[256];
|
||||
context.NonceRandomGenerator.NextBytes(randomData);
|
||||
useExplicitIV = TlsUtilities.IsTlsV11(context);
|
||||
encryptThenMac = context.SecurityParameters.encryptThenMac;
|
||||
int num = 2 * cipherKeySize + clientWriteDigest.GetDigestSize() + serverWriteDigest.GetDigestSize();
|
||||
if (!useExplicitIV)
|
||||
{
|
||||
num += clientWriteCipher.GetBlockSize() + serverWriteCipher.GetBlockSize();
|
||||
}
|
||||
byte[] array = TlsUtilities.CalculateKeyBlock(context, num);
|
||||
int num2 = 0;
|
||||
TlsMac tlsMac = new TlsMac(context, clientWriteDigest, array, num2, clientWriteDigest.GetDigestSize());
|
||||
num2 += clientWriteDigest.GetDigestSize();
|
||||
TlsMac tlsMac2 = new TlsMac(context, serverWriteDigest, array, num2, serverWriteDigest.GetDigestSize());
|
||||
num2 += serverWriteDigest.GetDigestSize();
|
||||
KeyParameter parameters = new KeyParameter(array, num2, cipherKeySize);
|
||||
num2 += cipherKeySize;
|
||||
KeyParameter parameters2 = new KeyParameter(array, num2, cipherKeySize);
|
||||
num2 += cipherKeySize;
|
||||
byte[] iv;
|
||||
byte[] iv2;
|
||||
if (useExplicitIV)
|
||||
{
|
||||
iv = new byte[clientWriteCipher.GetBlockSize()];
|
||||
iv2 = new byte[serverWriteCipher.GetBlockSize()];
|
||||
}
|
||||
else
|
||||
{
|
||||
iv = Arrays.CopyOfRange(array, num2, num2 + clientWriteCipher.GetBlockSize());
|
||||
num2 += clientWriteCipher.GetBlockSize();
|
||||
iv2 = Arrays.CopyOfRange(array, num2, num2 + serverWriteCipher.GetBlockSize());
|
||||
num2 += serverWriteCipher.GetBlockSize();
|
||||
}
|
||||
if (num2 != num)
|
||||
{
|
||||
throw new TlsFatalAlert(80);
|
||||
}
|
||||
ICipherParameters parameters3;
|
||||
ICipherParameters parameters4;
|
||||
if (context.IsServer)
|
||||
{
|
||||
mWriteMac = tlsMac2;
|
||||
mReadMac = tlsMac;
|
||||
encryptCipher = serverWriteCipher;
|
||||
decryptCipher = clientWriteCipher;
|
||||
parameters3 = new ParametersWithIV(parameters2, iv2);
|
||||
parameters4 = new ParametersWithIV(parameters, iv);
|
||||
}
|
||||
else
|
||||
{
|
||||
mWriteMac = tlsMac;
|
||||
mReadMac = tlsMac2;
|
||||
encryptCipher = clientWriteCipher;
|
||||
decryptCipher = serverWriteCipher;
|
||||
parameters3 = new ParametersWithIV(parameters, iv);
|
||||
parameters4 = new ParametersWithIV(parameters2, iv2);
|
||||
}
|
||||
encryptCipher.Init(forEncryption: true, parameters3);
|
||||
decryptCipher.Init(forEncryption: false, parameters4);
|
||||
}
|
||||
|
||||
public virtual int GetPlaintextLimit(int ciphertextLimit)
|
||||
{
|
||||
int blockSize = encryptCipher.GetBlockSize();
|
||||
int size = mWriteMac.Size;
|
||||
int num = ciphertextLimit;
|
||||
if (useExplicitIV)
|
||||
{
|
||||
num -= blockSize;
|
||||
}
|
||||
if (encryptThenMac)
|
||||
{
|
||||
num -= size;
|
||||
num -= num % blockSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
num -= num % blockSize;
|
||||
num -= size;
|
||||
}
|
||||
return num - 1;
|
||||
}
|
||||
|
||||
public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
|
||||
{
|
||||
int blockSize = encryptCipher.GetBlockSize();
|
||||
int size = mWriteMac.Size;
|
||||
ProtocolVersion serverVersion = context.ServerVersion;
|
||||
int num = len;
|
||||
if (!encryptThenMac)
|
||||
{
|
||||
num += size;
|
||||
}
|
||||
int num2 = blockSize - 1 - num % blockSize;
|
||||
if ((encryptThenMac || !context.SecurityParameters.truncatedHMac) && !serverVersion.IsDtls && !serverVersion.IsSsl)
|
||||
{
|
||||
int max = (255 - num2) / blockSize;
|
||||
int num3 = ChooseExtraPadBlocks(context.SecureRandom, max);
|
||||
num2 += num3 * blockSize;
|
||||
}
|
||||
int num4 = len + size + num2 + 1;
|
||||
if (useExplicitIV)
|
||||
{
|
||||
num4 += blockSize;
|
||||
}
|
||||
byte[] array = new byte[num4];
|
||||
int num5 = 0;
|
||||
if (useExplicitIV)
|
||||
{
|
||||
byte[] array2 = new byte[blockSize];
|
||||
context.NonceRandomGenerator.NextBytes(array2);
|
||||
encryptCipher.Init(forEncryption: true, new ParametersWithIV(null, array2));
|
||||
Array.Copy(array2, 0, array, num5, blockSize);
|
||||
num5 += blockSize;
|
||||
}
|
||||
int num6 = num5;
|
||||
Array.Copy(plaintext, offset, array, num5, len);
|
||||
num5 += len;
|
||||
if (!encryptThenMac)
|
||||
{
|
||||
byte[] array3 = mWriteMac.CalculateMac(seqNo, type, plaintext, offset, len);
|
||||
Array.Copy(array3, 0, array, num5, array3.Length);
|
||||
num5 += array3.Length;
|
||||
}
|
||||
for (int i = 0; i <= num2; i++)
|
||||
{
|
||||
array[num5++] = (byte)num2;
|
||||
}
|
||||
for (int j = num6; j < num5; j += blockSize)
|
||||
{
|
||||
encryptCipher.ProcessBlock(array, j, array, j);
|
||||
}
|
||||
if (encryptThenMac)
|
||||
{
|
||||
byte[] array4 = mWriteMac.CalculateMac(seqNo, type, array, 0, num5);
|
||||
Array.Copy(array4, 0, array, num5, array4.Length);
|
||||
num5 += array4.Length;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public virtual byte[] DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len)
|
||||
{
|
||||
int blockSize = decryptCipher.GetBlockSize();
|
||||
int size = mReadMac.Size;
|
||||
int num = blockSize;
|
||||
num = ((!encryptThenMac) ? System.Math.Max(num, size + 1) : (num + size));
|
||||
if (useExplicitIV)
|
||||
{
|
||||
num += blockSize;
|
||||
}
|
||||
if (len < num)
|
||||
{
|
||||
throw new TlsFatalAlert(50);
|
||||
}
|
||||
int num2 = len;
|
||||
if (encryptThenMac)
|
||||
{
|
||||
num2 -= size;
|
||||
}
|
||||
if (num2 % blockSize != 0)
|
||||
{
|
||||
throw new TlsFatalAlert(21);
|
||||
}
|
||||
if (encryptThenMac)
|
||||
{
|
||||
int num3 = offset + len;
|
||||
byte[] b = Arrays.CopyOfRange(ciphertext, num3 - size, num3);
|
||||
byte[] a = mReadMac.CalculateMac(seqNo, type, ciphertext, offset, len - size);
|
||||
if (!Arrays.ConstantTimeAreEqual(a, b))
|
||||
{
|
||||
throw new TlsFatalAlert(20);
|
||||
}
|
||||
}
|
||||
if (useExplicitIV)
|
||||
{
|
||||
decryptCipher.Init(forEncryption: false, new ParametersWithIV(null, ciphertext, offset, blockSize));
|
||||
offset += blockSize;
|
||||
num2 -= blockSize;
|
||||
}
|
||||
for (int i = 0; i < num2; i += blockSize)
|
||||
{
|
||||
decryptCipher.ProcessBlock(ciphertext, offset + i, ciphertext, offset + i);
|
||||
}
|
||||
int num4 = CheckPaddingConstantTime(ciphertext, offset, num2, blockSize, (!encryptThenMac) ? size : 0);
|
||||
bool flag = num4 == 0;
|
||||
int num5 = num2 - num4;
|
||||
if (!encryptThenMac)
|
||||
{
|
||||
num5 -= size;
|
||||
int num6 = num5;
|
||||
int num7 = offset + num6;
|
||||
byte[] b2 = Arrays.CopyOfRange(ciphertext, num7, num7 + size);
|
||||
byte[] a2 = mReadMac.CalculateMacConstantTime(seqNo, type, ciphertext, offset, num6, num2 - size, randomData);
|
||||
flag |= !Arrays.ConstantTimeAreEqual(a2, b2);
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
throw new TlsFatalAlert(20);
|
||||
}
|
||||
return Arrays.CopyOfRange(ciphertext, offset, offset + num5);
|
||||
}
|
||||
|
||||
protected virtual int CheckPaddingConstantTime(byte[] buf, int off, int len, int blockSize, int macSize)
|
||||
{
|
||||
int num = off + len;
|
||||
byte b = buf[num - 1];
|
||||
int num2 = b & 0xFF;
|
||||
int num3 = num2 + 1;
|
||||
int num4 = 0;
|
||||
byte b2 = 0;
|
||||
if ((TlsUtilities.IsSsl(context) && num3 > blockSize) || macSize + num3 > len)
|
||||
{
|
||||
num3 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int num5 = num - num3;
|
||||
do
|
||||
{
|
||||
b2 |= (byte)(buf[num5++] ^ b);
|
||||
}
|
||||
while (num5 < num);
|
||||
num4 = num3;
|
||||
if (b2 != 0)
|
||||
{
|
||||
num3 = 0;
|
||||
}
|
||||
}
|
||||
byte[] array = randomData;
|
||||
while (num4 < 256)
|
||||
{
|
||||
b2 |= (byte)(array[num4++] ^ b);
|
||||
}
|
||||
byte[] array2;
|
||||
(array2 = array)[0] = (byte)(array2[0] ^ b2);
|
||||
return num3;
|
||||
}
|
||||
|
||||
protected virtual int ChooseExtraPadBlocks(SecureRandom r, int max)
|
||||
{
|
||||
int x = r.NextInt();
|
||||
int val = LowestBitSet(x);
|
||||
return System.Math.Min(val, max);
|
||||
}
|
||||
|
||||
protected virtual int LowestBitSet(int x)
|
||||
{
|
||||
if (x == 0)
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
uint num = (uint)x;
|
||||
int num2 = 0;
|
||||
while ((num & 1) == 0)
|
||||
{
|
||||
num2++;
|
||||
num >>= 1;
|
||||
}
|
||||
return num2;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user