diff options
Diffstat (limited to 'crypto/src/crypto/prng/drbg/HMacSP800Drbg.cs')
-rw-r--r-- | crypto/src/crypto/prng/drbg/HMacSP800Drbg.cs | 66 |
1 files changed, 61 insertions, 5 deletions
diff --git a/crypto/src/crypto/prng/drbg/HMacSP800Drbg.cs b/crypto/src/crypto/prng/drbg/HMacSP800Drbg.cs index 0ec0e8b71..5a684a89d 100644 --- a/crypto/src/crypto/prng/drbg/HMacSP800Drbg.cs +++ b/crypto/src/crypto/prng/drbg/HMacSP800Drbg.cs @@ -107,15 +107,16 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg public int Generate(byte[] output, int outputOff, int outputLen, byte[] additionalInput, bool predictionResistant) { - int numberOfBits = outputLen * 8; +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + return Generate(output.AsSpan(outputOff, outputLen), additionalInput, predictionResistant); +#else + int numberOfBits = outputLen * 8; if (numberOfBits > MAX_BITS_REQUEST) throw new ArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST, "output"); if (mReseedCounter > RESEED_MAX) - { return -1; - } if (predictionResistant) { @@ -159,14 +160,69 @@ namespace Org.BouncyCastle.Crypto.Prng.Drbg Array.Copy(rv, 0, output, outputOff, outputLen); return numberOfBits; +#endif } - /** +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public int Generate(Span<byte> output, byte[] additionalInput, bool predictionResistant) + { + int outputLen = output.Length; + int numberOfBits = outputLen * 8; + + if (numberOfBits > MAX_BITS_REQUEST) + throw new ArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST, "output"); + + if (mReseedCounter > RESEED_MAX) + return -1; + + if (predictionResistant) + { + Reseed(additionalInput); + additionalInput = null; + } + + // 2. + if (additionalInput != null) + { + hmac_DRBG_Update(additionalInput); + } + + // 3. + int m = outputLen / mV.Length; + + mHMac.Init(new KeyParameter(mK)); + + for (int i = 0; i < m; i++) + { + mHMac.BlockUpdate(mV, 0, mV.Length); + mHMac.DoFinal(mV, 0); + + mV.CopyTo(output[(i * mV.Length)..]); + } + + int remaining = outputLen - m * mV.Length; + if (remaining > 0) + { + mHMac.BlockUpdate(mV, 0, mV.Length); + mHMac.DoFinal(mV, 0); + + mV[..remaining].CopyTo(output[(m * mV.Length)..]); + } + + hmac_DRBG_Update(additionalInput); + + mReseedCounter++; + + return numberOfBits; + } +#endif + + /** * Reseed the DRBG. * * @param additionalInput additional input to be added to the DRBG in this step. */ - public void Reseed(byte[] additionalInput) + public void Reseed(byte[] additionalInput) { byte[] entropy = GetEntropy(); byte[] seedMaterial = Arrays.Concatenate(entropy, additionalInput); |