From 7699428eb4416a52ae9a529c133839b2fd989903 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Wed, 5 Oct 2022 15:44:48 +0700 Subject: Various span usages --- crypto/src/crypto/agreement/srp/SRP6Utilities.cs | 117 ++++++++++++++++------- crypto/src/crypto/signers/HMacDsaKCalculator.cs | 50 +++++----- crypto/src/crypto/signers/X931Signer.cs | 18 ++-- crypto/src/openpgp/PgpPublicKey.cs | 12 ++- crypto/src/tls/crypto/impl/bc/BcTlsDHDomain.cs | 2 +- crypto/src/util/Arrays.cs | 18 ++++ 6 files changed, 143 insertions(+), 74 deletions(-) diff --git a/crypto/src/crypto/agreement/srp/SRP6Utilities.cs b/crypto/src/crypto/agreement/srp/SRP6Utilities.cs index ef6d8f24c..2176a7100 100644 --- a/crypto/src/crypto/agreement/srp/SRP6Utilities.cs +++ b/crypto/src/crypto/agreement/srp/SRP6Utilities.cs @@ -20,7 +20,10 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp public static BigInteger CalculateX(IDigest digest, BigInteger N, byte[] salt, byte[] identity, byte[] password) { - byte[] output = new byte[digest.GetDigestSize()]; +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + return CalculateX(digest, N, salt.AsSpan(), identity.AsSpan(), password.AsSpan()); +#else + byte[] output = new byte[digest.GetDigestSize()]; digest.BlockUpdate(identity, 0, identity.Length); digest.Update((byte)':'); @@ -32,9 +35,29 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp digest.DoFinal(output, 0); return new BigInteger(1, output); +#endif } - public static BigInteger GeneratePrivateValue(IDigest digest, BigInteger N, BigInteger g, SecureRandom random) +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static BigInteger CalculateX(IDigest digest, BigInteger N, ReadOnlySpan salt, + ReadOnlySpan identity, ReadOnlySpan password) + { + Span output = stackalloc byte[digest.GetDigestSize()]; + + digest.BlockUpdate(identity); + digest.Update((byte)':'); + digest.BlockUpdate(password); + digest.DoFinal(output); + + digest.BlockUpdate(salt); + digest.BlockUpdate(output); + digest.DoFinal(output); + + return new BigInteger(1, output); + } +#endif + + public static BigInteger GeneratePrivateValue(IDigest digest, BigInteger N, BigInteger g, SecureRandom random) { int minBits = System.Math.Min(256, N.BitLength / 2); BigInteger min = BigInteger.One.ShiftLeft(minBits - 1); @@ -95,59 +118,83 @@ namespace Org.BouncyCastle.Crypto.Agreement.Srp */ public static BigInteger CalculateKey(IDigest digest, BigInteger N, BigInteger S) { - int padLength = (N.BitLength + 7) / 8; - byte[] _S = GetPadded(S, padLength); - digest.BlockUpdate(_S, 0, _S.Length); + int paddedLength = (N.BitLength + 7) / 8; + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Span bytes = stackalloc byte[paddedLength]; + BigIntegers.AsUnsignedByteArray(S, bytes); + digest.BlockUpdate(bytes); + + Span output = stackalloc byte[digest.GetDigestSize()]; + 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()]; digest.DoFinal(output, 0); +#endif + return new BigInteger(1, output); } private static BigInteger HashPaddedTriplet(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2, BigInteger n3) { - int padLength = (N.BitLength + 7) / 8; - - byte[] n1_bytes = GetPadded(n1, padLength); - byte[] n2_bytes = GetPadded(n2, padLength); - byte[] n3_bytes = GetPadded(n3, padLength); - - digest.BlockUpdate(n1_bytes, 0, n1_bytes.Length); - digest.BlockUpdate(n2_bytes, 0, n2_bytes.Length); - digest.BlockUpdate(n3_bytes, 0, n3_bytes.Length); + int paddedLength = (N.BitLength + 7) / 8; + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Span bytes = stackalloc byte[paddedLength]; + BigIntegers.AsUnsignedByteArray(n1, bytes); + digest.BlockUpdate(bytes); + BigIntegers.AsUnsignedByteArray(n2, bytes); + digest.BlockUpdate(bytes); + BigIntegers.AsUnsignedByteArray(n3, bytes); + digest.BlockUpdate(bytes); + + Span output = stackalloc byte[digest.GetDigestSize()]; + digest.DoFinal(output); +#else + byte[] bytes = new byte[paddedLength]; + BigIntegers.AsUnsignedByteArray(n1, bytes, 0, bytes.Length); + digest.BlockUpdate(bytes, 0, bytes.Length); + BigIntegers.AsUnsignedByteArray(n2, bytes, 0, bytes.Length); + digest.BlockUpdate(bytes, 0, bytes.Length); + BigIntegers.AsUnsignedByteArray(n3, bytes, 0, bytes.Length); + digest.BlockUpdate(bytes, 0, bytes.Length); byte[] output = new byte[digest.GetDigestSize()]; digest.DoFinal(output, 0); +#endif return new BigInteger(1, output); } private static BigInteger HashPaddedPair(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2) { - int padLength = (N.BitLength + 7) / 8; - - byte[] n1_bytes = GetPadded(n1, padLength); - byte[] n2_bytes = GetPadded(n2, padLength); - - digest.BlockUpdate(n1_bytes, 0, n1_bytes.Length); - digest.BlockUpdate(n2_bytes, 0, n2_bytes.Length); + int paddedLength = (N.BitLength + 7) / 8; + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Span bytes = stackalloc byte[paddedLength]; + BigIntegers.AsUnsignedByteArray(n1, bytes); + digest.BlockUpdate(bytes); + BigIntegers.AsUnsignedByteArray(n2, bytes); + digest.BlockUpdate(bytes); + + Span output = stackalloc byte[digest.GetDigestSize()]; + digest.DoFinal(output); +#else + byte[] bytes = new byte[paddedLength]; + BigIntegers.AsUnsignedByteArray(n1, bytes, 0, bytes.Length); + digest.BlockUpdate(bytes, 0, bytes.Length); + BigIntegers.AsUnsignedByteArray(n2, bytes, 0, bytes.Length); + digest.BlockUpdate(bytes, 0, bytes.Length); byte[] output = new byte[digest.GetDigestSize()]; digest.DoFinal(output, 0); +#endif - return new BigInteger(1, output); - } - - private static byte[] GetPadded(BigInteger n, int length) - { - byte[] bs = BigIntegers.AsUnsignedByteArray(n); - if (bs.Length < length) - { - byte[] tmp = new byte[length]; - Array.Copy(bs, 0, tmp, length - bs.Length, bs.Length); - bs = tmp; - } - return bs; - } + return new BigInteger(1, output); + } } } diff --git a/crypto/src/crypto/signers/HMacDsaKCalculator.cs b/crypto/src/crypto/signers/HMacDsaKCalculator.cs index 2641f58b6..25e36530c 100644 --- a/crypto/src/crypto/signers/HMacDsaKCalculator.cs +++ b/crypto/src/crypto/signers/HMacDsaKCalculator.cs @@ -46,55 +46,55 @@ namespace Org.BouncyCastle.Crypto.Signers { this.n = n; - Arrays.Fill(V, (byte)0x01); - Arrays.Fill(K, (byte)0); - - int size = BigIntegers.GetUnsignedByteLength(n); - byte[] x = new byte[size]; - byte[] dVal = BigIntegers.AsUnsignedByteArray(d); - - Array.Copy(dVal, 0, x, x.Length - dVal.Length, dVal.Length); - - byte[] m = new byte[size]; + Arrays.Fill(V, 0x01); + Arrays.Fill(K, 0); BigInteger mInt = BitsToInt(message); - if (mInt.CompareTo(n) >= 0) { mInt = mInt.Subtract(n); } - byte[] mVal = BigIntegers.AsUnsignedByteArray(mInt); + int size = BigIntegers.GetUnsignedByteLength(n); - Array.Copy(mVal, 0, m, m.Length - mVal.Length, mVal.Length); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Span xm = stackalloc byte[size * 2]; + BigIntegers.AsUnsignedByteArray(d, xm[..size]); + BigIntegers.AsUnsignedByteArray(mInt, xm[size..]); +#else + byte[] x = BigIntegers.AsUnsignedByteArray(size, d); + byte[] m = BigIntegers.AsUnsignedByteArray(size, mInt); +#endif hMac.Init(new KeyParameter(K)); hMac.BlockUpdate(V, 0, V.Length); - hMac.Update((byte)0x00); + hMac.Update(0x00); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + hMac.BlockUpdate(xm); +#else hMac.BlockUpdate(x, 0, x.Length); hMac.BlockUpdate(m, 0, m.Length); +#endif InitAdditionalInput0(hMac); - hMac.DoFinal(K, 0); hMac.Init(new KeyParameter(K)); - hMac.BlockUpdate(V, 0, V.Length); - hMac.DoFinal(V, 0); hMac.BlockUpdate(V, 0, V.Length); - hMac.Update((byte)0x01); + hMac.Update(0x01); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + hMac.BlockUpdate(xm); +#else hMac.BlockUpdate(x, 0, x.Length); hMac.BlockUpdate(m, 0, m.Length); - +#endif hMac.DoFinal(K, 0); hMac.Init(new KeyParameter(K)); - hMac.BlockUpdate(V, 0, V.Length); - hMac.DoFinal(V, 0); } @@ -109,7 +109,6 @@ namespace Org.BouncyCastle.Crypto.Signers while (tOff < t.Length) { hMac.BlockUpdate(V, 0, V.Length); - hMac.DoFinal(V, 0); int len = System.Math.Min(t.Length - tOff, V.Length); @@ -120,19 +119,14 @@ namespace Org.BouncyCastle.Crypto.Signers BigInteger k = BitsToInt(t); if (k.SignValue > 0 && k.CompareTo(n) < 0) - { return k; - } hMac.BlockUpdate(V, 0, V.Length); - hMac.Update((byte)0x00); - + hMac.Update(0x00); hMac.DoFinal(K, 0); hMac.Init(new KeyParameter(K)); - hMac.BlockUpdate(V, 0, V.Length); - hMac.DoFinal(V, 0); } } diff --git a/crypto/src/crypto/signers/X931Signer.cs b/crypto/src/crypto/signers/X931Signer.cs index 6c0aa9427..278410f2a 100644 --- a/crypto/src/crypto/signers/X931Signer.cs +++ b/crypto/src/crypto/signers/X931Signer.cs @@ -3,6 +3,7 @@ using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.Zlib; namespace Org.BouncyCastle.Crypto.Signers { @@ -82,12 +83,6 @@ namespace Org.BouncyCastle.Crypto.Signers Reset(); } - /// clear possible sensitive data - private void ClearBlock(byte[] block) - { - Array.Clear(block, 0, block.Length); - } - public virtual void Update(byte b) { digest.Update(b); @@ -115,7 +110,7 @@ namespace Org.BouncyCastle.Crypto.Signers CreateSignatureBlock(); BigInteger t = new BigInteger(1, cipher.ProcessBlock(block, 0, block.Length)); - ClearBlock(block); + Arrays.Fill(block, 0x00); t = t.Min(kParam.Modulus.Subtract(t)); @@ -183,12 +178,17 @@ namespace Org.BouncyCastle.Crypto.Signers CreateSignatureBlock(); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Span fBlock = stackalloc byte[block.Length]; + BigIntegers.AsUnsignedByteArray(f, fBlock); +#else byte[] fBlock = BigIntegers.AsUnsignedByteArray(block.Length, f); +#endif bool rv = Arrays.ConstantTimeAreEqual(block, fBlock); - ClearBlock(block); - ClearBlock(fBlock); + Arrays.Fill(block, 0x00); + Arrays.Fill(fBlock, 0x00); return rv; } diff --git a/crypto/src/openpgp/PgpPublicKey.cs b/crypto/src/openpgp/PgpPublicKey.cs index 09c8b9743..6d5f35018 100644 --- a/crypto/src/openpgp/PgpPublicKey.cs +++ b/crypto/src/openpgp/PgpPublicKey.cs @@ -507,7 +507,17 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp { ECPublicBcpgKey ecK = (ECPublicBcpgKey)publicPk.Key; X9ECParameters x9 = ECKeyPairGenerator.FindECCurveByOid(ecK.CurveOid); - ECPoint q = x9.Curve.DecodePoint(BigIntegers.AsUnsignedByteArray(ecK.EncodedPoint)); + BigInteger encodedPoint = ecK.EncodedPoint; + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + int encodingLength = BigIntegers.GetUnsignedByteLength(encodedPoint); + Span encoding = stackalloc byte[encodingLength]; + BigIntegers.AsUnsignedByteArray(encodedPoint, encoding); + ECPoint q = x9.Curve.DecodePoint(encoding); +#else + ECPoint q = x9.Curve.DecodePoint(BigIntegers.AsUnsignedByteArray(encodedPoint)); +#endif + return new ECPublicKeyParameters(algorithm, q, ecK.CurveOid); } diff --git a/crypto/src/tls/crypto/impl/bc/BcTlsDHDomain.cs b/crypto/src/tls/crypto/impl/bc/BcTlsDHDomain.cs index faf6b4576..6a947c23b 100644 --- a/crypto/src/tls/crypto/impl/bc/BcTlsDHDomain.cs +++ b/crypto/src/tls/crypto/impl/bc/BcTlsDHDomain.cs @@ -24,7 +24,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC private static int GetValueLength(DHParameters dh) { - return (dh.P.BitLength + 7) / 8; + return BigIntegers.GetUnsignedByteLength(dh.P); } public static BcTlsSecret CalculateDHAgreement(BcTlsCrypto crypto, DHPrivateKeyParameters privateKey, diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs index c2ba9c3e1..e8dd02148 100644 --- a/crypto/src/util/Arrays.cs +++ b/crypto/src/util/Arrays.cs @@ -620,6 +620,24 @@ namespace Org.BouncyCastle.Utilities } } + public static void Fill(T[] ts, T t) + { + for (int i = 0; i < ts.Length; ++i) + { + ts[i] = t; + } + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static void Fill(Span ts, T t) + { + for (int i = 0; i < ts.Length; ++i) + { + ts[i] = t; + } + } +#endif + public static byte[] CopyOf(byte[] data, int newLength) { byte[] tmp = new byte[newLength]; -- cgit 1.4.1