diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-08-24 22:30:53 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-08-24 22:30:53 +0700 |
commit | cf62878dcfbb10a055dcbb460e1121cf3a693fb7 (patch) | |
tree | 654d0639d08f794e6f1f75df31b36418f5d0216f | |
parent | Fix GcmSivBlockCipher processing (diff) | |
download | BouncyCastle.NET-ed25519-cf62878dcfbb10a055dcbb460e1121cf3a693fb7.tar.xz |
Span-based variant for IAeadCipher.ProcessAadBytes
-rw-r--r-- | crypto/src/crypto/macs/GMac.cs | 11 | ||||
-rw-r--r-- | crypto/src/crypto/modes/CcmBlockCipher.cs | 8 | ||||
-rw-r--r-- | crypto/src/crypto/modes/ChaCha20Poly1305.cs | 13 | ||||
-rw-r--r-- | crypto/src/crypto/modes/EAXBlockCipher.cs | 15 | ||||
-rw-r--r-- | crypto/src/crypto/modes/GCMBlockCipher.cs | 46 | ||||
-rw-r--r-- | crypto/src/crypto/modes/GcmSivBlockCipher.cs | 77 | ||||
-rw-r--r-- | crypto/src/crypto/modes/IAeadCipher.cs | 7 | ||||
-rw-r--r-- | crypto/src/crypto/modes/KCcmBlockCipher.cs | 7 | ||||
-rw-r--r-- | crypto/src/crypto/modes/OCBBlockCipher.cs | 14 | ||||
-rw-r--r-- | crypto/src/crypto/modes/gcm/GcmUtilities.cs | 15 |
10 files changed, 196 insertions, 17 deletions
diff --git a/crypto/src/crypto/macs/GMac.cs b/crypto/src/crypto/macs/GMac.cs index 804097b3b..e0a448dda 100644 --- a/crypto/src/crypto/macs/GMac.cs +++ b/crypto/src/crypto/macs/GMac.cs @@ -89,16 +89,7 @@ namespace Org.BouncyCastle.Crypto.Macs #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER public void BlockUpdate(ReadOnlySpan<byte> input) { - // TODO[span] Add span-based variant of ProcessAadBytes - byte[] tmp = new byte[64]; - while (input.Length > 64) - { - input[..64].CopyTo(tmp); - input = input[64..]; - cipher.ProcessAadBytes(tmp, 0, 64); - } - input.CopyTo(tmp); - cipher.ProcessAadBytes(tmp, 0, input.Length); + cipher.ProcessAadBytes(input); } #endif diff --git a/crypto/src/crypto/modes/CcmBlockCipher.cs b/crypto/src/crypto/modes/CcmBlockCipher.cs index 8f0acce52..256cc1b13 100644 --- a/crypto/src/crypto/modes/CcmBlockCipher.cs +++ b/crypto/src/crypto/modes/CcmBlockCipher.cs @@ -117,6 +117,14 @@ namespace Org.BouncyCastle.Crypto.Modes associatedText.Write(inBytes, inOff, len); } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void ProcessAadBytes(ReadOnlySpan<byte> input) + { + // TODO: Process AAD online + associatedText.Write(input); + } +#endif + public virtual int ProcessByte( byte input, byte[] outBytes, diff --git a/crypto/src/crypto/modes/ChaCha20Poly1305.cs b/crypto/src/crypto/modes/ChaCha20Poly1305.cs index 462013200..385977fd5 100644 --- a/crypto/src/crypto/modes/ChaCha20Poly1305.cs +++ b/crypto/src/crypto/modes/ChaCha20Poly1305.cs @@ -209,6 +209,19 @@ namespace Org.BouncyCastle.Crypto.Modes } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void ProcessAadBytes(ReadOnlySpan<byte> input) + { + CheckAad(); + + if (!input.IsEmpty) + { + this.mAadCount = IncrementCount(mAadCount, (uint)input.Length, AadLimit); + mPoly1305.BlockUpdate(input); + } + } +#endif + public virtual int ProcessByte(byte input, byte[] outBytes, int outOff) { CheckData(); diff --git a/crypto/src/crypto/modes/EAXBlockCipher.cs b/crypto/src/crypto/modes/EAXBlockCipher.cs index 624f385b5..ffe32ec68 100644 --- a/crypto/src/crypto/modes/EAXBlockCipher.cs +++ b/crypto/src/crypto/modes/EAXBlockCipher.cs @@ -194,13 +194,22 @@ namespace Org.BouncyCastle.Crypto.Modes public virtual void ProcessAadBytes(byte[] inBytes, int inOff, int len) { if (cipherInitialized) - { throw new InvalidOperationException("AAD data cannot be added after encryption/decryption processing has begun."); - } + mac.BlockUpdate(inBytes, inOff, len); } - public virtual int ProcessByte( +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void ProcessAadBytes(ReadOnlySpan<byte> input) + { + if (cipherInitialized) + throw new InvalidOperationException("AAD data cannot be added after encryption/decryption processing has begun."); + + mac.BlockUpdate(input); + } +#endif + + public virtual int ProcessByte( byte input, byte[] outBytes, int outOff) diff --git a/crypto/src/crypto/modes/GCMBlockCipher.cs b/crypto/src/crypto/modes/GCMBlockCipher.cs index ac54e9762..bf9c14e28 100644 --- a/crypto/src/crypto/modes/GCMBlockCipher.cs +++ b/crypto/src/crypto/modes/GCMBlockCipher.cs @@ -278,6 +278,9 @@ namespace Org.BouncyCastle.Crypto.Modes public virtual void ProcessAadBytes(byte[] inBytes, int inOff, int len) { +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + ProcessAadBytes(inBytes.AsSpan(inOff, len)); +#else CheckStatus(); if (atBlockPos > 0) @@ -309,7 +312,42 @@ namespace Org.BouncyCastle.Crypto.Modes atBlockPos = BlockSize + inLimit - inOff; Array.Copy(inBytes, inOff, atBlock, 0, atBlockPos); +#endif + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void ProcessAadBytes(ReadOnlySpan<byte> input) + { + CheckStatus(); + + if (atBlockPos > 0) + { + int available = BlockSize - atBlockPos; + if (input.Length < available) + { + input.CopyTo(atBlock.AsSpan(atBlockPos)); + atBlockPos += input.Length; + return; + } + + input[..available].CopyTo(atBlock.AsSpan(atBlockPos)); + gHASHBlock(S_at, atBlock); + atLength += BlockSize; + input = input[available..]; + //atBlockPos = 0; + } + + while (input.Length >= BlockSize) + { + gHASHBlock(S_at, input); + atLength += BlockSize; + input = input[BlockSize..]; + } + + input.CopyTo(atBlock); + atBlockPos = input.Length; } +#endif private void InitCipher() { @@ -930,6 +968,13 @@ namespace Org.BouncyCastle.Crypto.Modes } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + private void gHASHBlock(byte[] Y, ReadOnlySpan<byte> b) + { + GcmUtilities.Xor(Y, b); + multiplier.MultiplyH(Y); + } +#else private void gHASHBlock(byte[] Y, byte[] b) { GcmUtilities.Xor(Y, b); @@ -941,6 +986,7 @@ namespace Org.BouncyCastle.Crypto.Modes GcmUtilities.Xor(Y, b, off); multiplier.MultiplyH(Y); } +#endif private void gHASHPartial(byte[] Y, byte[] b, int off, int len) { diff --git a/crypto/src/crypto/modes/GcmSivBlockCipher.cs b/crypto/src/crypto/modes/GcmSivBlockCipher.cs index 63808a53a..284a952a6 100644 --- a/crypto/src/crypto/modes/GcmSivBlockCipher.cs +++ b/crypto/src/crypto/modes/GcmSivBlockCipher.cs @@ -1,7 +1,6 @@ using System; using System.IO; -using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Modes.Gcm; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Utilities; @@ -296,15 +295,30 @@ namespace Org.BouncyCastle.Crypto.Modes public virtual void ProcessAadBytes(byte[] pData, int pOffset, int pLen) { - /* Check that we can supply AEAD */ - CheckAeadStatus(pLen); - /* Check input buffer */ CheckBuffer(pData, pOffset, pLen, false); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + ProcessAadBytes(pData.AsSpan(pOffset, pLen)); +#else + /* Check that we can supply AEAD */ + CheckAeadStatus(pLen); + /* Process the aead */ theAEADHasher.updateHash(pData, pOffset, pLen); +#endif + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void ProcessAadBytes(ReadOnlySpan<byte> input) + { + /* Check that we can supply AEAD */ + CheckAeadStatus(input.Length); + + /* Process the aead */ + theAEADHasher.updateHash(input); } +#endif public virtual int ProcessByte(byte pByte, byte[] pOutput, int pOutOffset) { @@ -647,6 +661,18 @@ namespace Org.BouncyCastle.Crypto.Modes } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + private static void fillReverse(ReadOnlySpan<byte> input, Span<byte> output) + { + /* Loop through the buffer */ + for (int i = 0, j = BUFLEN - 1; i < input.Length; i++, j--) + { + /* Copy byte */ + output[j] = input[i]; + } + } +#endif + /** * xor a full block buffer. * @param pLeft the left operand and result @@ -891,6 +917,49 @@ namespace Org.BouncyCastle.Crypto.Modes numHashed += (ulong)pLen; } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + internal void updateHash(ReadOnlySpan<byte> buffer) + { + int pLen = buffer.Length; + + /* If we should process the cache */ + int mySpace = BUFLEN - numActive; + if (numActive > 0 && buffer.Length >= mySpace) + { + /* Copy data into the cache and hash it */ + buffer[..mySpace].CopyTo(theBuffer.AsSpan(numActive)); + fillReverse(theBuffer, parent.theReverse); + parent.gHASH(parent.theReverse); + + /* Adjust counters */ + buffer = buffer[mySpace..]; + numActive = 0; + } + + /* While we have full blocks */ + while (buffer.Length >= BUFLEN) + { + /* Access the next data */ + fillReverse(buffer[..BUFLEN], parent.theReverse); + parent.gHASH(parent.theReverse); + + /* Adjust counters */ + buffer = buffer[BUFLEN..]; + } + + /* If we have remaining data */ + if (!buffer.IsEmpty) + { + /* Copy data into the cache */ + buffer.CopyTo(theBuffer.AsSpan(numActive)); + numActive += buffer.Length; + } + + /* Adjust the number of bytes processed */ + numHashed += (ulong)pLen; + } +#endif + /** * complete hash. */ diff --git a/crypto/src/crypto/modes/IAeadCipher.cs b/crypto/src/crypto/modes/IAeadCipher.cs index 437693cb6..c61e13b01 100644 --- a/crypto/src/crypto/modes/IAeadCipher.cs +++ b/crypto/src/crypto/modes/IAeadCipher.cs @@ -41,6 +41,13 @@ namespace Org.BouncyCastle.Crypto.Modes /// <param name="len">The number of bytes to be processed.</param> void ProcessAadBytes(byte[] inBytes, int inOff, int len); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + /// <summary>Add a span of bytes to the associated data check.</summary> + /// <remarks>If the implementation supports it, this will be an online operation and will not retain the associated data.</remarks> + /// <param name="input">the span containing the data.</param> + void ProcessAadBytes(ReadOnlySpan<byte> input); +#endif + /** * Encrypt/decrypt a single byte. * diff --git a/crypto/src/crypto/modes/KCcmBlockCipher.cs b/crypto/src/crypto/modes/KCcmBlockCipher.cs index afa7063a3..afa68a794 100644 --- a/crypto/src/crypto/modes/KCcmBlockCipher.cs +++ b/crypto/src/crypto/modes/KCcmBlockCipher.cs @@ -158,6 +158,13 @@ namespace Org.BouncyCastle.Crypto.Modes associatedText.Write(input, inOff, len); } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void ProcessAadBytes(ReadOnlySpan<byte> input) + { + associatedText.Write(input); + } +#endif + private void ProcessAAD(byte[] assocText, int assocOff, int assocLen, int dataLen) { if (assocLen - assocOff < engine.GetBlockSize()) diff --git a/crypto/src/crypto/modes/OCBBlockCipher.cs b/crypto/src/crypto/modes/OCBBlockCipher.cs index 28e88a6c9..db6aa39ae 100644 --- a/crypto/src/crypto/modes/OCBBlockCipher.cs +++ b/crypto/src/crypto/modes/OCBBlockCipher.cs @@ -287,6 +287,20 @@ namespace Org.BouncyCastle.Crypto.Modes } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void ProcessAadBytes(ReadOnlySpan<byte> input) + { + for (int i = 0; i < input.Length; ++i) + { + hashBlock[hashBlockPos] = input[i]; + if (++hashBlockPos == hashBlock.Length) + { + ProcessHashBlock(); + } + } + } +#endif + public virtual int ProcessByte(byte input, byte[] output, int outOff) { mainBlock[mainBlockPos] = input; diff --git a/crypto/src/crypto/modes/gcm/GcmUtilities.cs b/crypto/src/crypto/modes/gcm/GcmUtilities.cs index 676d74107..78a1f0860 100644 --- a/crypto/src/crypto/modes/gcm/GcmUtilities.cs +++ b/crypto/src/crypto/modes/gcm/GcmUtilities.cs @@ -275,6 +275,21 @@ namespace Org.BouncyCastle.Crypto.Modes.Gcm z.n1 = x.n1 ^ y.n1; } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + internal static void Xor(Span<byte> x, ReadOnlySpan<byte> y) + { + int i = 0; + do + { + x[i] ^= y[i]; ++i; + x[i] ^= y[i]; ++i; + x[i] ^= y[i]; ++i; + x[i] ^= y[i]; ++i; + } + while (i < 16); + } +#endif + private static ulong ImplMul64(ulong x, ulong y) { ulong x0 = x & 0x1111111111111111UL; |