diff options
-rw-r--r-- | crypto/src/crypto/modes/GCMBlockCipher.cs | 41 |
1 files changed, 28 insertions, 13 deletions
diff --git a/crypto/src/crypto/modes/GCMBlockCipher.cs b/crypto/src/crypto/modes/GCMBlockCipher.cs index 9ab3a8e8c..26b590ef9 100644 --- a/crypto/src/crypto/modes/GCMBlockCipher.cs +++ b/crypto/src/crypto/modes/GCMBlockCipher.cs @@ -1084,14 +1084,14 @@ namespace Org.BouncyCastle.Crypto.Modes InitCipher(); } - Span<byte> ctrBlock = stackalloc byte[BlockSize]; + Span<byte> ctrBlocks = stackalloc byte[BlockSize * 2]; + GetNextCtrBlocks2(ctrBlocks); - GetNextCtrBlock(ctrBlock); #if NETCOREAPP3_0_OR_GREATER if (Sse2.IsSupported && Unsafe.SizeOf<Vector128<byte>>() == BlockSize) { var t0 = MemoryMarshal.Read<Vector128<byte>>(input); - var t1 = MemoryMarshal.Read<Vector128<byte>>(ctrBlock); + var t1 = MemoryMarshal.Read<Vector128<byte>>(ctrBlocks); var t2 = MemoryMarshal.Read<Vector128<byte>>(S.AsSpan()); t1 = Sse2.Xor(t1, t0); @@ -1105,10 +1105,10 @@ namespace Org.BouncyCastle.Crypto.Modes { for (int i = 0; i < BlockSize; i += 4) { - byte c0 = (byte)(ctrBlock[i + 0] ^ input[i + 0]); - byte c1 = (byte)(ctrBlock[i + 1] ^ input[i + 1]); - byte c2 = (byte)(ctrBlock[i + 2] ^ input[i + 2]); - byte c3 = (byte)(ctrBlock[i + 3] ^ input[i + 3]); + byte c0 = (byte)(ctrBlocks[i + 0] ^ input[i + 0]); + byte c1 = (byte)(ctrBlocks[i + 1] ^ input[i + 1]); + byte c2 = (byte)(ctrBlocks[i + 2] ^ input[i + 2]); + byte c3 = (byte)(ctrBlocks[i + 3] ^ input[i + 3]); S[i + 0] ^= c0; S[i + 1] ^= c1; @@ -1125,13 +1125,13 @@ namespace Org.BouncyCastle.Crypto.Modes input = input[BlockSize..]; output = output[BlockSize..]; + ctrBlocks = ctrBlocks[BlockSize..]; - GetNextCtrBlock(ctrBlock); #if NETCOREAPP3_0_OR_GREATER if (Sse2.IsSupported && Unsafe.SizeOf<Vector128<byte>>() == BlockSize) { var t0 = MemoryMarshal.Read<Vector128<byte>>(input); - var t1 = MemoryMarshal.Read<Vector128<byte>>(ctrBlock); + var t1 = MemoryMarshal.Read<Vector128<byte>>(ctrBlocks); var t2 = MemoryMarshal.Read<Vector128<byte>>(S.AsSpan()); t1 = Sse2.Xor(t1, t0); @@ -1145,10 +1145,10 @@ namespace Org.BouncyCastle.Crypto.Modes { for (int i = 0; i < BlockSize; i += 4) { - byte c0 = (byte)(ctrBlock[i + 0] ^ input[i + 0]); - byte c1 = (byte)(ctrBlock[i + 1] ^ input[i + 1]); - byte c2 = (byte)(ctrBlock[i + 2] ^ input[i + 2]); - byte c3 = (byte)(ctrBlock[i + 3] ^ input[i + 3]); + byte c0 = (byte)(ctrBlocks[i + 0] ^ input[i + 0]); + byte c1 = (byte)(ctrBlocks[i + 1] ^ input[i + 1]); + byte c2 = (byte)(ctrBlocks[i + 2] ^ input[i + 2]); + byte c3 = (byte)(ctrBlocks[i + 3] ^ input[i + 3]); S[i + 0] ^= c0; S[i + 1] ^= c1; @@ -1179,6 +1179,21 @@ namespace Org.BouncyCastle.Crypto.Modes cipher.ProcessBlock(counter, block); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void GetNextCtrBlocks2(Span<byte> blocks) + { + if (blocksRemaining < 2) + throw new InvalidOperationException("Attempt to process too many blocks"); + + blocksRemaining -= 2; + + Pack.UInt32_To_BE(++counter32, counter, 12); + cipher.ProcessBlock(counter, blocks); + + Pack.UInt32_To_BE(++counter32, counter, 12); + cipher.ProcessBlock(counter, blocks[BlockSize..]); + } + private void ProcessPartial(Span<byte> partialBlock, Span<byte> output) { Span<byte> ctrBlock = stackalloc byte[BlockSize]; |