summary refs log tree commit diff
path: root/crypto/src
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-08-19 15:13:06 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-08-19 15:13:06 +0700
commitcf1ad240147c298b6adabad399a8bf0f5756f606 (patch)
tree32c456ebb4e0470df04d6633cac88af2985286b7 /crypto/src
parentRemove unnecessary TODO (diff)
downloadBouncyCastle.NET-ed25519-cf1ad240147c298b6adabad399a8bf0f5756f606.tar.xz
Implement NextBytes(Span<byte)
Diffstat (limited to 'crypto/src')
-rw-r--r--crypto/src/crypto/prng/CryptoApiRandomGenerator.cs13
-rw-r--r--crypto/src/crypto/prng/DigestRandomGenerator.cs22
-rw-r--r--crypto/src/crypto/prng/IRandomGenerator.cs4
-rw-r--r--crypto/src/crypto/prng/SP800SecureRandom.cs7
-rw-r--r--crypto/src/crypto/prng/VMPCRandomGenerator.cs18
-rw-r--r--crypto/src/crypto/prng/X931Rng.cs61
-rw-r--r--crypto/src/crypto/prng/X931SecureRandom.cs15
-rw-r--r--crypto/src/security/SecureRandom.cs16
8 files changed, 155 insertions, 1 deletions
diff --git a/crypto/src/crypto/prng/CryptoApiRandomGenerator.cs b/crypto/src/crypto/prng/CryptoApiRandomGenerator.cs
index 7803ddd3d..11d29a818 100644
--- a/crypto/src/crypto/prng/CryptoApiRandomGenerator.cs
+++ b/crypto/src/crypto/prng/CryptoApiRandomGenerator.cs
@@ -45,6 +45,9 @@ namespace Org.BouncyCastle.Crypto.Prng
             if (bytes.Length < (start + len))
                 throw new ArgumentException("Byte array too small for requested offset and length");
 
+#if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_0_OR_GREATER
+            rndProv.GetBytes(bytes, start, len);
+#else
             if (bytes.Length == len && start == 0) 
             {
                 NextBytes(bytes);
@@ -55,8 +58,16 @@ namespace Org.BouncyCastle.Crypto.Prng
                 NextBytes(tmpBuf);
                 Array.Copy(tmpBuf, 0, bytes, start, len);
             }
+#endif
         }
 
-        #endregion
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public virtual void NextBytes(Span<byte> bytes)
+        {
+            rndProv.GetBytes(bytes);
+        }
+#endif
+
+#endregion
     }
 }
diff --git a/crypto/src/crypto/prng/DigestRandomGenerator.cs b/crypto/src/crypto/prng/DigestRandomGenerator.cs
index 024db2852..3587956b6 100644
--- a/crypto/src/crypto/prng/DigestRandomGenerator.cs
+++ b/crypto/src/crypto/prng/DigestRandomGenerator.cs
@@ -90,6 +90,28 @@ namespace Org.BouncyCastle.Crypto.Prng
 			}
 		}
 
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+		public virtual void NextBytes(Span<byte> bytes)
+		{
+			lock (this)
+			{
+				int stateOff = 0;
+
+				GenerateState();
+
+				for (int i = 0; i < bytes.Length; ++i)
+				{
+					if (stateOff == state.Length)
+					{
+						GenerateState();
+						stateOff = 0;
+					}
+					bytes[i] = state[stateOff++];
+				}
+			}
+		}
+#endif
+
 		private void CycleSeed()
 		{
 			DigestUpdate(seed);
diff --git a/crypto/src/crypto/prng/IRandomGenerator.cs b/crypto/src/crypto/prng/IRandomGenerator.cs
index 8dbe4068f..051f8f8c6 100644
--- a/crypto/src/crypto/prng/IRandomGenerator.cs
+++ b/crypto/src/crypto/prng/IRandomGenerator.cs
@@ -22,5 +22,9 @@ namespace Org.BouncyCastle.Crypto.Prng
 		/// <param name="start">Index to start filling at.</param>
 		/// <param name="len">Length of segment to fill.</param>
 		void NextBytes(byte[] bytes, int start, int len);
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+		void NextBytes(Span<byte> bytes);
+#endif
 	}
 }
diff --git a/crypto/src/crypto/prng/SP800SecureRandom.cs b/crypto/src/crypto/prng/SP800SecureRandom.cs
index 2e1484125..fb5c3a677 100644
--- a/crypto/src/crypto/prng/SP800SecureRandom.cs
+++ b/crypto/src/crypto/prng/SP800SecureRandom.cs
@@ -70,6 +70,13 @@ namespace Org.BouncyCastle.Crypto.Prng
             }
         }
 
+        // TODO Add efficient override (needs ISP80090Drbg support for spans)
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+//        public override void NextBytes(Span<byte> buffer)
+//        {
+//        }
+//#endif
+
         public override byte[] GenerateSeed(int numBytes)
         {
             return EntropyUtilities.GenerateSeed(mEntropySource, numBytes);
diff --git a/crypto/src/crypto/prng/VMPCRandomGenerator.cs b/crypto/src/crypto/prng/VMPCRandomGenerator.cs
index 64f287d13..72e6b5e7d 100644
--- a/crypto/src/crypto/prng/VMPCRandomGenerator.cs
+++ b/crypto/src/crypto/prng/VMPCRandomGenerator.cs
@@ -110,5 +110,23 @@ namespace Org.BouncyCastle.Crypto.Prng
                 }
             }
         }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public virtual void NextBytes(Span<byte> bytes)
+        {
+            lock (P) 
+            {
+                for (int i = 0; i != bytes.Length; i++) 
+                {
+                    s = P[(s + P[n & 0xff]) & 0xff];
+                    bytes[i] = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
+                    byte temp = P[n & 0xff];
+                    P[n & 0xff] = P[s & 0xff];
+                    P[s & 0xff] = temp;
+                    n = (byte) ((n + 1) & 0xff);
+                }
+            }
+        }
+#endif
     }
 }
diff --git a/crypto/src/crypto/prng/X931Rng.cs b/crypto/src/crypto/prng/X931Rng.cs
index 53c982c25..f0bfdc9f1 100644
--- a/crypto/src/crypto/prng/X931Rng.cs
+++ b/crypto/src/crypto/prng/X931Rng.cs
@@ -103,6 +103,67 @@ namespace Org.BouncyCastle.Crypto.Prng
             return outputLen * 8;
         }
 
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        internal int Generate(Span<byte> output, bool predictionResistant)
+        {
+            int outputLen = output.Length;
+
+            if (mR.Length == 8) // 64 bit block size
+            {
+                if (mReseedCounter > BLOCK64_RESEED_MAX)
+                    return -1;
+
+                if (outputLen > BLOCK64_MAX_BITS_REQUEST / 8)
+                    throw new ArgumentException("Number of bits per request limited to " + BLOCK64_MAX_BITS_REQUEST, "output");
+            }
+            else
+            {
+                if (mReseedCounter > BLOCK128_RESEED_MAX)
+                    return -1;
+
+                if (outputLen > BLOCK128_MAX_BITS_REQUEST / 8)
+                    throw new ArgumentException("Number of bits per request limited to " + BLOCK128_MAX_BITS_REQUEST, "output");
+            }
+
+            if (predictionResistant || mV == null)
+            {
+                mV = mEntropySource.GetEntropy();
+                if (mV.Length != mEngine.GetBlockSize())
+                    throw new InvalidOperationException("Insufficient entropy returned");
+            }
+
+            int m = outputLen / mR.Length;
+
+            for (int i = 0; i < m; i++)
+            {
+                mEngine.ProcessBlock(mDT, 0, mI, 0);
+                Process(mR, mI, mV);
+                Process(mV, mR, mI);
+
+                mR.CopyTo(output[(i * mR.Length)..]);
+
+                Increment(mDT);
+            }
+
+            int bytesToCopy = (outputLen - m * mR.Length);
+
+            if (bytesToCopy > 0)
+            {
+                mEngine.ProcessBlock(mDT, 0, mI, 0);
+                Process(mR, mI, mV);
+                Process(mV, mR, mI);
+
+                mR.AsSpan(0, bytesToCopy).CopyTo(output[(m * mR.Length)..]);
+
+                Increment(mDT);
+            }
+
+            mReseedCounter++;
+
+            return outputLen * 8;
+        }
+#endif
+
         /**
          * Reseed the RNG.
          */
diff --git a/crypto/src/crypto/prng/X931SecureRandom.cs b/crypto/src/crypto/prng/X931SecureRandom.cs
index 1402e5c31..01678af8f 100644
--- a/crypto/src/crypto/prng/X931SecureRandom.cs
+++ b/crypto/src/crypto/prng/X931SecureRandom.cs
@@ -60,6 +60,21 @@ namespace Org.BouncyCastle.Crypto.Prng
             }
         }
 
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public override void NextBytes(Span<byte> buffer)
+        {
+            lock (this)
+            {
+                // check if a reseed is required...
+                if (mDrbg.Generate(buffer, mPredictionResistant) < 0)
+                {
+                    mDrbg.Reseed();
+                    mDrbg.Generate(buffer, mPredictionResistant);
+                }
+            }
+        }
+#endif
+
         public override byte[] GenerateSeed(int numBytes)
         {
             return EntropyUtilities.GenerateSeed(mDrbg.EntropySource, numBytes);
diff --git a/crypto/src/security/SecureRandom.cs b/crypto/src/security/SecureRandom.cs
index e8cac56f5..4e118e77a 100644
--- a/crypto/src/security/SecureRandom.cs
+++ b/crypto/src/security/SecureRandom.cs
@@ -181,6 +181,22 @@ namespace Org.BouncyCastle.Security
             generator.NextBytes(buf, off, len);
         }
 
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public override void NextBytes(Span<byte> buffer)
+        {
+            if (generator != null)
+            {
+                generator.NextBytes(buffer);
+            }
+            else
+            {
+                byte[] tmp = new byte[buffer.Length];
+                NextBytes(tmp);
+                tmp.CopyTo(buffer);
+            }
+        }
+#endif
+
         private static readonly double DoubleScale = 1.0 / Convert.ToDouble(1L << 53);
 
         public override double NextDouble()