From 2d28fafa7fe1becdada43f939b5121946468052c Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Thu, 6 Oct 2022 12:19:49 +0700 Subject: Refactor stackalloc usage --- crypto/src/bcpg/ECDHPublicBCPGKey.cs | 4 +-- crypto/src/bcpg/MPInteger.cs | 22 ++++++------- crypto/src/crypto/agreement/kdf/DHKekGenerator.cs | 4 ++- crypto/src/crypto/agreement/srp/SRP6Utilities.cs | 38 ++++++++++++++++------ crypto/src/crypto/digests/ShortenedDigest.cs | 5 ++- crypto/src/crypto/engines/SM2Engine.cs | 26 +++++++++++---- .../src/crypto/generators/BaseKdfBytesGenerator.cs | 4 ++- crypto/src/crypto/io/CipherStream.cs | 4 ++- crypto/src/crypto/modes/CtsBlockCipher.cs | 8 +++-- crypto/src/crypto/modes/EAXBlockCipher.cs | 6 +++- crypto/src/crypto/modes/KCcmBlockCipher.cs | 4 ++- crypto/src/crypto/signers/HMacDsaKCalculator.cs | 5 ++- crypto/src/crypto/signers/X931Signer.cs | 5 ++- crypto/src/math/ec/ECAlgorithms.cs | 5 ++- crypto/src/math/ec/rfc8032/Ed25519.cs | 5 ++- crypto/src/openpgp/PgpPublicKey.cs | 6 ++-- 16 files changed, 108 insertions(+), 43 deletions(-) (limited to 'crypto') diff --git a/crypto/src/bcpg/ECDHPublicBCPGKey.cs b/crypto/src/bcpg/ECDHPublicBCPGKey.cs index 05c34ba8b..5b6d9460e 100644 --- a/crypto/src/bcpg/ECDHPublicBCPGKey.cs +++ b/crypto/src/bcpg/ECDHPublicBCPGKey.cs @@ -22,9 +22,9 @@ namespace Org.BouncyCastle.Bcpg throw new InvalidOperationException("KDF parameters size of 3 expected."); #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - Span kdfParameters = stackalloc byte[length]; + Span kdfParameters = stackalloc byte[3]; #else - byte[] kdfParameters = new byte[length]; + byte[] kdfParameters = new byte[3]; #endif bcpgIn.ReadFully(kdfParameters); diff --git a/crypto/src/bcpg/MPInteger.cs b/crypto/src/bcpg/MPInteger.cs index 2f564b00c..eb59be6e5 100644 --- a/crypto/src/bcpg/MPInteger.cs +++ b/crypto/src/bcpg/MPInteger.cs @@ -20,16 +20,13 @@ namespace Org.BouncyCastle.Bcpg int lengthInBytes = (lengthInBits + 7) / 8; #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - if (lengthInBytes <= 512) - { - Span span = stackalloc byte[lengthInBytes]; - bcpgIn.ReadFully(span); - m_val = new BigInteger(1, span); - return; - } + Span bytes = lengthInBytes <= 512 + ? stackalloc byte[lengthInBytes] + : new byte[lengthInBytes]; +#else + byte[] bytes = new byte[lengthInBytes]; #endif - byte[] bytes = new byte[lengthInBytes]; bcpgIn.ReadFully(bytes); m_val = new BigInteger(1, bytes); } @@ -55,12 +52,15 @@ namespace Org.BouncyCastle.Bcpg internal static BigInteger ToMpiBigInteger(ECPoint point) { #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - Span encoding = stackalloc byte[point.GetEncodedLength(false)]; + int encodedLength = point.GetEncodedLength(false); + Span encoding = encodedLength <= 512 + ? stackalloc byte[encodedLength] + : new byte[encodedLength]; point.EncodeTo(false, encoding); - return new BigInteger(1, encoding); #else - return new BigInteger(1, point.GetEncoded(false)); + byte[] encoding = point.GetEncoded(false); #endif + return new BigInteger(1, encoding); } } } diff --git a/crypto/src/crypto/agreement/kdf/DHKekGenerator.cs b/crypto/src/crypto/agreement/kdf/DHKekGenerator.cs index 7d75c2224..2dabe9d1f 100644 --- a/crypto/src/crypto/agreement/kdf/DHKekGenerator.cs +++ b/crypto/src/crypto/agreement/kdf/DHKekGenerator.cs @@ -120,7 +120,9 @@ namespace Org.BouncyCastle.Crypto.Agreement.Kdf int cThreshold = (int)((oBytes + digestSize - 1) / digestSize); - Span dig = stackalloc byte[digestSize]; + Span dig = digestSize <= 128 + ? stackalloc byte[digestSize] + : new byte[digestSize]; uint counter = 1; diff --git a/crypto/src/crypto/agreement/srp/SRP6Utilities.cs b/crypto/src/crypto/agreement/srp/SRP6Utilities.cs index 2176a7100..73be57c5a 100644 --- a/crypto/src/crypto/agreement/srp/SRP6Utilities.cs +++ b/crypto/src/crypto/agreement/srp/SRP6Utilities.cs @@ -42,7 +42,10 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp public static BigInteger CalculateX(IDigest digest, BigInteger N, ReadOnlySpan salt, ReadOnlySpan identity, ReadOnlySpan password) { - Span output = stackalloc byte[digest.GetDigestSize()]; + int digestSize = digest.GetDigestSize(); + Span output = digestSize <= 128 + ? stackalloc byte[digestSize] + : new byte[digestSize]; digest.BlockUpdate(identity); digest.Update((byte)':'); @@ -119,20 +122,25 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp public static BigInteger CalculateKey(IDigest digest, BigInteger N, BigInteger S) { int paddedLength = (N.BitLength + 7) / 8; + int digestSize = digest.GetDigestSize(); #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - Span bytes = stackalloc byte[paddedLength]; + Span bytes = paddedLength <= 512 + ? stackalloc byte[paddedLength] + : new byte[paddedLength]; BigIntegers.AsUnsignedByteArray(S, bytes); digest.BlockUpdate(bytes); - Span output = stackalloc byte[digest.GetDigestSize()]; + Span output = digestSize <= 128 + ? stackalloc byte[digestSize] + : new byte[digestSize]; digest.DoFinal(output); #else byte[] bytes = new byte[paddedLength]; BigIntegers.AsUnsignedByteArray(S, bytes, 0, bytes.Length); digest.BlockUpdate(bytes, 0, bytes.Length); - byte[] output = new byte[digest.GetDigestSize()]; + byte[] output = new byte[digestSize]; digest.DoFinal(output, 0); #endif @@ -142,9 +150,12 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp private static BigInteger HashPaddedTriplet(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2, BigInteger n3) { int paddedLength = (N.BitLength + 7) / 8; + int digestSize = digest.GetDigestSize(); #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - Span bytes = stackalloc byte[paddedLength]; + Span bytes = paddedLength <= 512 + ? stackalloc byte[paddedLength] + : new byte[paddedLength]; BigIntegers.AsUnsignedByteArray(n1, bytes); digest.BlockUpdate(bytes); BigIntegers.AsUnsignedByteArray(n2, bytes); @@ -152,7 +163,9 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp BigIntegers.AsUnsignedByteArray(n3, bytes); digest.BlockUpdate(bytes); - Span output = stackalloc byte[digest.GetDigestSize()]; + Span output = digestSize <= 128 + ? stackalloc byte[digestSize] + : new byte[digestSize]; digest.DoFinal(output); #else byte[] bytes = new byte[paddedLength]; @@ -163,7 +176,7 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp BigIntegers.AsUnsignedByteArray(n3, bytes, 0, bytes.Length); digest.BlockUpdate(bytes, 0, bytes.Length); - byte[] output = new byte[digest.GetDigestSize()]; + byte[] output = new byte[digestSize]; digest.DoFinal(output, 0); #endif @@ -173,15 +186,20 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp private static BigInteger HashPaddedPair(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2) { int paddedLength = (N.BitLength + 7) / 8; + int digestSize = digest.GetDigestSize(); #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - Span bytes = stackalloc byte[paddedLength]; + Span bytes = paddedLength <= 512 + ? stackalloc byte[paddedLength] + : new byte[paddedLength]; BigIntegers.AsUnsignedByteArray(n1, bytes); digest.BlockUpdate(bytes); BigIntegers.AsUnsignedByteArray(n2, bytes); digest.BlockUpdate(bytes); - Span output = stackalloc byte[digest.GetDigestSize()]; + Span output = digestSize <= 128 + ? stackalloc byte[digestSize] + : new byte[digestSize]; digest.DoFinal(output); #else byte[] bytes = new byte[paddedLength]; @@ -190,7 +208,7 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp BigIntegers.AsUnsignedByteArray(n2, bytes, 0, bytes.Length); digest.BlockUpdate(bytes, 0, bytes.Length); - byte[] output = new byte[digest.GetDigestSize()]; + byte[] output = new byte[digestSize]; digest.DoFinal(output, 0); #endif diff --git a/crypto/src/crypto/digests/ShortenedDigest.cs b/crypto/src/crypto/digests/ShortenedDigest.cs index 9e9998560..0ea3cc1a1 100644 --- a/crypto/src/crypto/digests/ShortenedDigest.cs +++ b/crypto/src/crypto/digests/ShortenedDigest.cs @@ -78,7 +78,10 @@ namespace Org.BouncyCastle.Crypto.Digests #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER public int DoFinal(Span output) { - Span tmp = stackalloc byte[baseDigest.GetDigestSize()]; + int baseDigestSize = baseDigest.GetDigestSize(); + Span tmp = baseDigestSize <= 128 + ? stackalloc byte[baseDigestSize] + : new byte[baseDigestSize]; baseDigest.DoFinal(tmp); diff --git a/crypto/src/crypto/engines/SM2Engine.cs b/crypto/src/crypto/engines/SM2Engine.cs index 36593cddc..e0734d424 100644 --- a/crypto/src/crypto/engines/SM2Engine.cs +++ b/crypto/src/crypto/engines/SM2Engine.cs @@ -138,14 +138,20 @@ namespace Org.BouncyCastle.Crypto.Engines ECPoint c1P = multiplier.Multiply(mECParams.G, k).Normalize(); - Span c1 = stackalloc byte[c1P.GetEncodedLength(false)]; + int c1PEncodedLength = c1P.GetEncodedLength(false); + Span c1 = c1PEncodedLength <= 512 + ? stackalloc byte[c1PEncodedLength] + : new byte[c1PEncodedLength]; c1P.EncodeTo(false, c1); AddFieldElement(mDigest, kPB.AffineXCoord); mDigest.BlockUpdate(input); AddFieldElement(mDigest, kPB.AffineYCoord); - Span c3 = stackalloc byte[mDigest.GetDigestSize()]; + int digestSize = mDigest.GetDigestSize(); + Span c3 = digestSize <= 128 + ? stackalloc byte[digestSize] + : new byte[digestSize]; mDigest.DoFinal(c3); switch (mMode) @@ -187,7 +193,9 @@ namespace Org.BouncyCastle.Crypto.Engines mDigest.BlockUpdate(c2); AddFieldElement(mDigest, c1P.AffineYCoord); - Span c3 = stackalloc byte[mDigest.GetDigestSize()]; + Span c3 = digestSize <= 128 + ? stackalloc byte[digestSize] + : new byte[digestSize]; mDigest.DoFinal(c3); int check = 0; @@ -343,10 +351,13 @@ namespace Org.BouncyCastle.Crypto.Engines private void Kdf(IDigest digest, ECPoint c1, byte[] encData) { int digestSize = digest.GetDigestSize(); + int bufSize = System.Math.Max(4, digestSize); #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - Span buf = stackalloc byte[System.Math.Max(4, digestSize)]; + Span buf = bufSize <= 128 + ? stackalloc byte[bufSize] + : new byte[bufSize]; #else - byte[] buf = new byte[System.Math.Max(4, digestSize)]; + byte[] buf = new byte[bufSize]; #endif int off = 0; @@ -426,7 +437,10 @@ namespace Org.BouncyCastle.Crypto.Engines private void AddFieldElement(IDigest digest, ECFieldElement v) { #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - Span p = stackalloc byte[v.GetEncodedLength()]; + int encodedLength = v.GetEncodedLength(); + Span p = encodedLength <= 128 + ? stackalloc byte[encodedLength] + : new byte[encodedLength]; v.EncodeTo(p); digest.BlockUpdate(p); #else diff --git a/crypto/src/crypto/generators/BaseKdfBytesGenerator.cs b/crypto/src/crypto/generators/BaseKdfBytesGenerator.cs index c0c4be217..a1839dc33 100644 --- a/crypto/src/crypto/generators/BaseKdfBytesGenerator.cs +++ b/crypto/src/crypto/generators/BaseKdfBytesGenerator.cs @@ -142,7 +142,9 @@ namespace Org.BouncyCastle.Crypto.Generators int cThreshold = (int)((oBytes + digestSize - 1) / digestSize); - Span dig = stackalloc byte[digestSize]; + Span dig = digestSize <= 128 + ? stackalloc byte[digestSize] + : new byte[digestSize]; Span C = stackalloc byte[4]; Pack.UInt32_To_BE((uint)counterStart, C); diff --git a/crypto/src/crypto/io/CipherStream.cs b/crypto/src/crypto/io/CipherStream.cs index e59f33679..145fa7fd3 100644 --- a/crypto/src/crypto/io/CipherStream.cs +++ b/crypto/src/crypto/io/CipherStream.cs @@ -258,7 +258,9 @@ namespace Org.BouncyCastle.Crypto.IO { #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER int outputSize = m_writeCipher.GetOutputSize(0); - Span output = stackalloc byte[outputSize]; + Span output = outputSize <= 256 + ? stackalloc byte[outputSize] + : new byte[outputSize]; int len = m_writeCipher.DoFinal(output); m_stream.Write(output[..len]); #else diff --git a/crypto/src/crypto/modes/CtsBlockCipher.cs b/crypto/src/crypto/modes/CtsBlockCipher.cs index 022e86675..e76049a36 100644 --- a/crypto/src/crypto/modes/CtsBlockCipher.cs +++ b/crypto/src/crypto/modes/CtsBlockCipher.cs @@ -294,7 +294,9 @@ namespace Org.BouncyCastle.Crypto.Modes int blockSize = m_cipherMode.GetBlockSize(); int length = bufOff - blockSize; - Span block = stackalloc byte[blockSize]; + Span block = blockSize <= 64 + ? stackalloc byte[blockSize] + : new byte[blockSize]; if (forEncryption) { @@ -319,7 +321,9 @@ namespace Org.BouncyCastle.Crypto.Modes } else { - Span lastBlock = stackalloc byte[blockSize]; + Span lastBlock = blockSize <= 64 + ? stackalloc byte[blockSize] + : new byte[blockSize]; m_cipherMode.UnderlyingCipher.ProcessBlock(buf, block); diff --git a/crypto/src/crypto/modes/EAXBlockCipher.cs b/crypto/src/crypto/modes/EAXBlockCipher.cs index 5d7f05d02..770c432e2 100644 --- a/crypto/src/crypto/modes/EAXBlockCipher.cs +++ b/crypto/src/crypto/modes/EAXBlockCipher.cs @@ -316,7 +316,11 @@ namespace Org.BouncyCastle.Crypto.Modes InitCipher(); int extra = bufOff; - Span tmp = stackalloc byte[bufBlock.Length]; + int tmpLength = bufBlock.Length; + + Span tmp = tmpLength <= 128 + ? stackalloc byte[tmpLength] + : new byte[tmpLength]; bufOff = 0; diff --git a/crypto/src/crypto/modes/KCcmBlockCipher.cs b/crypto/src/crypto/modes/KCcmBlockCipher.cs index a733379cc..cc4a5060c 100644 --- a/crypto/src/crypto/modes/KCcmBlockCipher.cs +++ b/crypto/src/crypto/modes/KCcmBlockCipher.cs @@ -459,7 +459,9 @@ namespace Org.BouncyCastle.Crypto.Modes Array.Copy(macBlock, 0, mac, 0, macSize); - Span calculatedMac = stackalloc byte[macSize]; + Span calculatedMac = macSize <= 64 + ? stackalloc byte[macSize] + : new byte[macSize]; buffer.AsSpan(0, macSize).CopyTo(calculatedMac); diff --git a/crypto/src/crypto/signers/HMacDsaKCalculator.cs b/crypto/src/crypto/signers/HMacDsaKCalculator.cs index 25e36530c..67dadede8 100644 --- a/crypto/src/crypto/signers/HMacDsaKCalculator.cs +++ b/crypto/src/crypto/signers/HMacDsaKCalculator.cs @@ -58,7 +58,10 @@ namespace Org.BouncyCastle.Crypto.Signers int size = BigIntegers.GetUnsignedByteLength(n); #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - Span xm = stackalloc byte[size * 2]; + int xmSize = size * 2; + Span xm = xmSize <= 512 + ? stackalloc byte[xmSize] + : new byte[xmSize]; BigIntegers.AsUnsignedByteArray(d, xm[..size]); BigIntegers.AsUnsignedByteArray(mInt, xm[size..]); #else diff --git a/crypto/src/crypto/signers/X931Signer.cs b/crypto/src/crypto/signers/X931Signer.cs index 278410f2a..40255c40c 100644 --- a/crypto/src/crypto/signers/X931Signer.cs +++ b/crypto/src/crypto/signers/X931Signer.cs @@ -179,7 +179,10 @@ namespace Org.BouncyCastle.Crypto.Signers CreateSignatureBlock(); #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - Span fBlock = stackalloc byte[block.Length]; + int fBlockSize = block.Length; + Span fBlock = fBlockSize <= 512 + ? stackalloc byte[fBlockSize] + : new byte[fBlockSize]; BigIntegers.AsUnsignedByteArray(f, fBlock); #else byte[] fBlock = BigIntegers.AsUnsignedByteArray(block.Length, f); diff --git a/crypto/src/math/ec/ECAlgorithms.cs b/crypto/src/math/ec/ECAlgorithms.cs index fcfab06f7..3059ca3b3 100644 --- a/crypto/src/math/ec/ECAlgorithms.cs +++ b/crypto/src/math/ec/ECAlgorithms.cs @@ -216,7 +216,10 @@ namespace Org.BouncyCastle.Math.EC throw new ArgumentException("Point must be on the same curve", nameof(p)); #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - Span encoding = stackalloc byte[p.GetEncodedLength(false)]; + int encodedLength = p.GetEncodedLength(false); + Span encoding = encodedLength <= 512 + ? stackalloc byte[encodedLength] + : new byte[encodedLength]; p.EncodeTo(false, encoding); return c.DecodePoint(encoding); #else diff --git a/crypto/src/math/ec/rfc8032/Ed25519.cs b/crypto/src/math/ec/rfc8032/Ed25519.cs index d6bf461cf..f3b63f3b3 100644 --- a/crypto/src/math/ec/rfc8032/Ed25519.cs +++ b/crypto/src/math/ec/rfc8032/Ed25519.cs @@ -433,7 +433,10 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 public static void GeneratePublicKey(ReadOnlySpan sk, Span pk) { IDigest d = CreateDigest(); - Span h = stackalloc byte[d.GetDigestSize()]; + int digestSize = d.GetDigestSize(); + Span h = digestSize <= 128 + ? stackalloc byte[digestSize] + : new byte[digestSize]; d.BlockUpdate(sk[..SecretKeySize]); d.DoFinal(h); diff --git a/crypto/src/openpgp/PgpPublicKey.cs b/crypto/src/openpgp/PgpPublicKey.cs index 6d5f35018..cdb8efd36 100644 --- a/crypto/src/openpgp/PgpPublicKey.cs +++ b/crypto/src/openpgp/PgpPublicKey.cs @@ -510,8 +510,10 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp BigInteger encodedPoint = ecK.EncodedPoint; #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - int encodingLength = BigIntegers.GetUnsignedByteLength(encodedPoint); - Span encoding = stackalloc byte[encodingLength]; + int encodedLength = BigIntegers.GetUnsignedByteLength(encodedPoint); + Span encoding = encodedLength <= 512 + ? stackalloc byte[encodedLength] + : new byte[encodedLength]; BigIntegers.AsUnsignedByteArray(encodedPoint, encoding); ECPoint q = x9.Curve.DecodePoint(encoding); #else -- cgit 1.4.1