diff --git a/crypto/src/crypto/IMac.cs b/crypto/src/crypto/IMac.cs
index 03a86e8b6..3df4c354f 100644
--- a/crypto/src/crypto/IMac.cs
+++ b/crypto/src/crypto/IMac.cs
@@ -2,68 +2,44 @@ using System;
namespace Org.BouncyCastle.Crypto
{
- /**
- * The base interface for implementations of message authentication codes (MACs).
- */
+ /// <summary>The base interface for implementations of message authentication codes (MACs).</summary>
public interface IMac
{
- /**
- * Initialise the MAC.
- *
- * @param param the key and other data required by the MAC.
- * @exception ArgumentException if the parameters argument is
- * inappropriate.
- */
+ /// <summary>Initialise the MAC.</summary>
+ /// <param name="parameters">The key or other data required by the MAC.</param>
void Init(ICipherParameters parameters);
- /**
- * Return the name of the algorithm the MAC implements.
- *
- * @return the name of the algorithm the MAC implements.
- */
+ /// <summary>The algorithm name.</summary>
string AlgorithmName { get; }
- /**
- * Return the block size for this MAC (in bytes).
- *
- * @return the block size for this MAC in bytes.
- */
- int GetMacSize();
+ /// <summary>Return the size, in bytes, of the MAC produced by this implementation.</summary>
+ /// <returns>the size, in bytes, of the MAC produced by this implementation.</returns>
+ int GetMacSize();
- /**
- * add a single byte to the mac for processing.
- *
- * @param in the byte to be processed.
- * @exception InvalidOperationException if the MAC is not initialised.
- */
+ /// <summary>Update the MAC with a single byte.</summary>
+ /// <param name="input">the input byte to be entered.</param>
void Update(byte input);
- /**
- * @param in the array containing the input.
- * @param inOff the index in the array the data begins at.
- * @param len the length of the input starting at inOff.
- * @exception InvalidOperationException if the MAC is not initialised.
- * @exception DataLengthException if there isn't enough data in in.
- */
- void BlockUpdate(byte[] input, int inOff, int len);
+ /// <summary>Update the MAC with a block of bytes.</summary>
+ /// <param name="input">the byte array containing the data.</param>
+ /// <param name="inOff">the offset into the byte array where the data starts.</param>
+ /// <param name="inLen">the length of the data.</param>
+ void BlockUpdate(byte[] input, int inOff, int inLen);
- /**
- * Compute the final stage of the MAC writing the output to the out
- * parameter.
- * <p>
- * doFinal leaves the MAC in the same state it was after the last init.
- * </p>
- * @param out the array the MAC is to be output to.
- * @param outOff the offset into the out buffer the output is to start at.
- * @exception DataLengthException if there isn't enough space in out.
- * @exception InvalidOperationException if the MAC is not initialised.
- */
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ /// <summary>Update the MAC with a span of bytes.</summary>
+ /// <param name="input">the span containing the data.</param>
+ void BlockUpdate(ReadOnlySpan<byte> input);
+#endif
+
+ /// <summary>Perform final calculations, producing the result MAC.</summary>
+ /// <remarks>This call leaves the MAC reset.</remarks>
+ /// <param name="output">the byte array the MAC is to be copied into.</param>
+ /// <param name="outOff">the offset into the byte array the MAC is to start at.</param>
+ /// <returns>the number of bytes written</returns>
int DoFinal(byte[] output, int outOff);
- /**
- * Reset the MAC. At the end of resetting the MAC should be in the
- * in the same state it was after the last init (if there was one).
- */
+ /// <summary>Reset the MAC back to its initial state.</summary>
void Reset();
}
}
diff --git a/crypto/src/crypto/digests/SkeinDigest.cs b/crypto/src/crypto/digests/SkeinDigest.cs
index 3dba9ec75..d56c0e788 100644
--- a/crypto/src/crypto/digests/SkeinDigest.cs
+++ b/crypto/src/crypto/digests/SkeinDigest.cs
@@ -102,7 +102,7 @@ namespace Org.BouncyCastle.Crypto.Digests
public void BlockUpdate(byte[] inBytes, int inOff, int len)
{
- engine.Update(inBytes, inOff, len);
+ engine.BlockUpdate(inBytes, inOff, len);
}
public int DoFinal(byte[] outBytes, int outOff)
@@ -113,7 +113,7 @@ namespace Org.BouncyCastle.Crypto.Digests
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
public void BlockUpdate(ReadOnlySpan<byte> input)
{
- engine.Update(input);
+ engine.BlockUpdate(input);
}
public int DoFinal(Span<byte> output)
diff --git a/crypto/src/crypto/digests/SkeinEngine.cs b/crypto/src/crypto/digests/SkeinEngine.cs
index 86aa3c938..2535f786a 100644
--- a/crypto/src/crypto/digests/SkeinEngine.cs
+++ b/crypto/src/crypto/digests/SkeinEngine.cs
@@ -752,17 +752,17 @@ namespace Org.BouncyCastle.Crypto.Digests
public void Update(byte inByte)
{
singleByte[0] = inByte;
- Update(singleByte, 0, 1);
+ BlockUpdate(singleByte, 0, 1);
}
- public void Update(byte[] inBytes, int inOff, int len)
+ public void BlockUpdate(byte[] inBytes, int inOff, int len)
{
CheckInitialised();
ubi.Update(inBytes, inOff, len, chain);
}
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- public void Update(ReadOnlySpan<byte> input)
+ public void BlockUpdate(ReadOnlySpan<byte> input)
{
CheckInitialised();
ubi.Update(input, chain);
diff --git a/crypto/src/crypto/macs/CMac.cs b/crypto/src/crypto/macs/CMac.cs
index 682c12bac..dbd696429 100644
--- a/crypto/src/crypto/macs/CMac.cs
+++ b/crypto/src/crypto/macs/CMac.cs
@@ -132,8 +132,7 @@ namespace Org.BouncyCastle.Crypto.Macs
return ret;
}
- public void Init(
- ICipherParameters parameters)
+ public void Init(ICipherParameters parameters)
{
if (parameters is KeyParameter)
{
@@ -159,8 +158,7 @@ namespace Org.BouncyCastle.Crypto.Macs
return macSize;
}
- public void Update(
- byte input)
+ public void Update(byte input)
{
if (bufOff == buf.Length)
{
@@ -171,14 +169,14 @@ namespace Org.BouncyCastle.Crypto.Macs
buf[bufOff++] = input;
}
- public void BlockUpdate(
- byte[] inBytes,
- int inOff,
- int len)
+ public void BlockUpdate(byte[] inBytes, int inOff, int len)
{
if (len < 0)
throw new ArgumentException("Can't have a negative input length!");
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ BlockUpdate(inBytes.AsSpan(inOff, len));
+#else
int blockSize = cipher.GetBlockSize();
int gapLen = blockSize - bufOff;
@@ -204,8 +202,37 @@ namespace Org.BouncyCastle.Crypto.Macs
Array.Copy(inBytes, inOff, buf, bufOff, len);
bufOff += len;
+#endif
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void BlockUpdate(ReadOnlySpan<byte> input)
+ {
+ int blockSize = cipher.GetBlockSize();
+ int gapLen = blockSize - bufOff;
+
+ if (input.Length > gapLen)
+ {
+ input[..gapLen].CopyTo(buf.AsSpan(bufOff));
+
+ cipher.ProcessBlock(buf, mac);
+
+ bufOff = 0;
+ input = input[gapLen..];
+
+ while (input.Length > blockSize)
+ {
+ cipher.ProcessBlock(input, mac);
+ input = input[blockSize..];
+ }
+ }
+
+ input.CopyTo(buf.AsSpan(bufOff));
+
+ bufOff += input.Length;
+ }
+#endif
+
public int DoFinal(
byte[] outBytes,
int outOff)
diff --git a/crypto/src/crypto/macs/CbcBlockCipherMac.cs b/crypto/src/crypto/macs/CbcBlockCipherMac.cs
index 146e16aa8..de7a5f2e4 100644
--- a/crypto/src/crypto/macs/CbcBlockCipherMac.cs
+++ b/crypto/src/crypto/macs/CbcBlockCipherMac.cs
@@ -99,8 +99,7 @@ namespace Org.BouncyCastle.Crypto.Macs
get { return cipher.AlgorithmName; }
}
- public void Init(
- ICipherParameters parameters)
+ public void Init(ICipherParameters parameters)
{
Reset();
@@ -112,8 +111,7 @@ namespace Org.BouncyCastle.Crypto.Macs
return macSize;
}
- public void Update(
- byte input)
+ public void Update(byte input)
{
if (bufOff == buf.Length)
{
@@ -124,15 +122,15 @@ namespace Org.BouncyCastle.Crypto.Macs
buf[bufOff++] = input;
}
- public void BlockUpdate(
- byte[] input,
- int inOff,
- int len)
+ public void BlockUpdate(byte[] input, int inOff, int len)
{
if (len < 0)
throw new ArgumentException("Can't have a negative input length!");
- int blockSize = cipher.GetBlockSize();
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ BlockUpdate(input.AsSpan(inOff, len));
+#else
+ int blockSize = cipher.GetBlockSize();
int gapLen = blockSize - bufOff;
if (len > gapLen)
@@ -157,7 +155,36 @@ namespace Org.BouncyCastle.Crypto.Macs
Array.Copy(input, inOff, buf, bufOff, len);
bufOff += len;
+#endif
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void BlockUpdate(ReadOnlySpan<byte> input)
+ {
+ int blockSize = cipher.GetBlockSize();
+ int gapLen = blockSize - bufOff;
+
+ if (input.Length > gapLen)
+ {
+ input[..gapLen].CopyTo(buf.AsSpan(bufOff));
+
+ cipher.ProcessBlock(buf, buf);
+
+ bufOff = 0;
+ input = input[gapLen..];
+
+ while (input.Length > blockSize)
+ {
+ cipher.ProcessBlock(input, buf);
+ input = input[blockSize..];
+ }
+ }
+
+ input.CopyTo(buf.AsSpan(bufOff));
+
+ bufOff += input.Length;
}
+#endif
public int DoFinal(
byte[] output,
diff --git a/crypto/src/crypto/macs/CfbBlockCipherMac.cs b/crypto/src/crypto/macs/CfbBlockCipherMac.cs
index e10bb438d..b454306e3 100644
--- a/crypto/src/crypto/macs/CfbBlockCipherMac.cs
+++ b/crypto/src/crypto/macs/CfbBlockCipherMac.cs
@@ -263,8 +263,7 @@ namespace Org.BouncyCastle.Crypto.Macs
get { return cipher.AlgorithmName; }
}
- public void Init(
- ICipherParameters parameters)
+ public void Init(ICipherParameters parameters)
{
Reset();
@@ -276,8 +275,7 @@ namespace Org.BouncyCastle.Crypto.Macs
return macSize;
}
- public void Update(
- byte input)
+ public void Update(byte input)
{
if (bufOff == Buffer.Length)
{
@@ -288,15 +286,15 @@ namespace Org.BouncyCastle.Crypto.Macs
Buffer[bufOff++] = input;
}
- public void BlockUpdate(
- byte[] input,
- int inOff,
- int len)
+ public void BlockUpdate(byte[] input, int inOff, int len)
{
if (len < 0)
throw new ArgumentException("Can't have a negative input length!");
- int blockSize = cipher.GetBlockSize();
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ BlockUpdate(input.AsSpan(inOff, len));
+#else
+ int blockSize = cipher.GetBlockSize();
int resultLen = 0;
int gapLen = blockSize - bufOff;
@@ -322,11 +320,39 @@ namespace Org.BouncyCastle.Crypto.Macs
Array.Copy(input, inOff, Buffer, bufOff, len);
bufOff += len;
+#endif
}
- public int DoFinal(
- byte[] output,
- int outOff)
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void BlockUpdate(ReadOnlySpan<byte> input)
+ {
+ int blockSize = cipher.GetBlockSize();
+ int resultLen = 0;
+ int gapLen = blockSize - bufOff;
+
+ if (input.Length > gapLen)
+ {
+ input[..gapLen].CopyTo(Buffer.AsSpan(bufOff));
+
+ resultLen += cipher.ProcessBlock(Buffer, mac);
+
+ bufOff = 0;
+ input = input[gapLen..];
+
+ while (input.Length > blockSize)
+ {
+ resultLen += cipher.ProcessBlock(input, mac);
+ input = input[blockSize..];
+ }
+ }
+
+ input.CopyTo(Buffer.AsSpan(bufOff));
+
+ bufOff += input.Length;
+ }
+#endif
+
+ public int DoFinal(byte[] output, int outOff)
{
int blockSize = cipher.GetBlockSize();
@@ -367,5 +393,4 @@ namespace Org.BouncyCastle.Crypto.Macs
cipher.Reset();
}
}
-
}
diff --git a/crypto/src/crypto/macs/DSTU7564Mac.cs b/crypto/src/crypto/macs/DSTU7564Mac.cs
index fc905cc99..43fe7fb90 100644
--- a/crypto/src/crypto/macs/DSTU7564Mac.cs
+++ b/crypto/src/crypto/macs/DSTU7564Mac.cs
@@ -70,6 +70,17 @@ namespace Org.BouncyCastle.Crypto.Macs
inputLength += (ulong)len;
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void BlockUpdate(ReadOnlySpan<byte> input)
+ {
+ if (paddedKey == null)
+ throw new InvalidOperationException(AlgorithmName + " not initialised");
+
+ engine.BlockUpdate(input);
+ inputLength += (ulong)input.Length;
+ }
+#endif
+
public void Update(byte input)
{
engine.Update(input);
diff --git a/crypto/src/crypto/macs/DSTU7624Mac.cs b/crypto/src/crypto/macs/DSTU7624Mac.cs
index 953d8164f..01c1f869c 100644
--- a/crypto/src/crypto/macs/DSTU7624Mac.cs
+++ b/crypto/src/crypto/macs/DSTU7624Mac.cs
@@ -1,87 +1,89 @@
using System;
-using Org.BouncyCastle.Utilities;
-using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
-
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Macs
{
- /**
+ /**
* implementation of DSTU 7624 MAC
*/
- public class Dstu7624Mac : IMac
- {
- private int macSize;
-
- private Dstu7624Engine engine;
- private int blockSize;
+ public class Dstu7624Mac : IMac
+ {
+ private int macSize;
+
+ private Dstu7624Engine engine;
+ private int blockSize;
+
+ private byte[] c, cTemp, kDelta;
+ private byte[] buf;
+ private int bufOff;
+
+ public Dstu7624Mac(int blockSizeBits, int q)
+ {
+ engine = new Dstu7624Engine(blockSizeBits);
+
+ blockSize = blockSizeBits / 8;
- private byte[] c, cTemp, kDelta;
- private byte[] buf;
- private int bufOff;
+ macSize = q / 8;
- public Dstu7624Mac(int blockSizeBits, int q)
- {
- engine = new Dstu7624Engine(blockSizeBits);
+ c = new byte[blockSize];
- blockSize = blockSizeBits / 8;
+ cTemp = new byte[blockSize];
- macSize = q / 8;
+ kDelta = new byte[blockSize];
+ buf = new byte[blockSize];
+ }
+
+ public void Init(ICipherParameters parameters)
+ {
+ if (parameters is KeyParameter)
+ {
+ engine.Init(true, (KeyParameter)parameters);
+
+ engine.ProcessBlock(kDelta, 0, kDelta, 0);
+ }
+ else
+ {
+ throw new ArgumentException("invalid parameter passed to Dstu7624Mac init - "
+ + Platform.GetTypeName(parameters));
+ }
+ }
- c = new byte[blockSize];
-
- cTemp = new byte[blockSize];
+ public string AlgorithmName
+ {
+ get { return "Dstu7624Mac"; }
+ }
- kDelta = new byte[blockSize];
- buf = new byte[blockSize];
+ public int GetMacSize()
+ {
+ return macSize;
}
- public void Init(ICipherParameters parameters)
- {
- if (parameters is KeyParameter)
- {
- engine.Init(true, (KeyParameter)parameters);
-
- engine.ProcessBlock(kDelta, 0, kDelta, 0);
- }
- else
- {
- throw new ArgumentException("invalid parameter passed to Dstu7624Mac init - "
- + Platform.GetTypeName(parameters));
- }
- }
-
- public string AlgorithmName
- {
- get { return "Dstu7624Mac"; }
- }
-
- public int GetMacSize()
- {
- return macSize;
- }
-
- public void Update(byte input)
- {
+ public void Update(byte input)
+ {
if (bufOff == buf.Length)
{
- processBlock(buf, 0);
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ ProcessBlock(buf);
+#else
+ ProcessBlock(buf, 0);
+#endif
bufOff = 0;
}
buf[bufOff++] = input;
}
- public void BlockUpdate(byte[] input, int inOff, int len)
- {
+ public void BlockUpdate(byte[] input, int inOff, int len)
+ {
if (len < 0)
- {
- throw new ArgumentException(
- "Can't have a negative input length!");
- }
+ throw new ArgumentException("Can't have a negative input length!");
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ BlockUpdate(input.AsSpan(inOff, len));
+#else
int blockSize = engine.GetBlockSize();
int gapLen = blockSize - bufOff;
@@ -89,7 +91,7 @@ namespace Org.BouncyCastle.Crypto.Macs
{
Array.Copy(input, inOff, buf, bufOff, gapLen);
- processBlock(buf, 0);
+ ProcessBlock(buf, 0);
bufOff = 0;
len -= gapLen;
@@ -97,7 +99,7 @@ namespace Org.BouncyCastle.Crypto.Macs
while (len > blockSize)
{
- processBlock(input, inOff);
+ ProcessBlock(input, inOff);
len -= blockSize;
inOff += blockSize;
@@ -107,29 +109,73 @@ namespace Org.BouncyCastle.Crypto.Macs
Array.Copy(input, inOff, buf, bufOff, len);
bufOff += len;
+#endif
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void BlockUpdate(ReadOnlySpan<byte> input)
+ {
+ int blockSize = engine.GetBlockSize();
+ int gapLen = blockSize - bufOff;
+
+ if (input.Length > gapLen)
+ {
+ input[..gapLen].CopyTo(buf.AsSpan(bufOff));
+
+ ProcessBlock(buf);
+
+ bufOff = 0;
+ input = input[gapLen..];
+
+ while (input.Length > blockSize)
+ {
+ ProcessBlock(input);
+ input = input[blockSize..];
+ }
+ }
+
+ input.CopyTo(buf.AsSpan(bufOff));
+
+ bufOff += input.Length;
+ }
+#endif
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ private void ProcessBlock(ReadOnlySpan<byte> input)
+ {
+ Xor(c, input, cTemp);
+
+ engine.ProcessBlock(cTemp, c);
}
- private void processBlock(byte[] input, int inOff)
+ private void Xor(ReadOnlySpan<byte> c, ReadOnlySpan<byte> input, Span<byte> xorResult)
+ {
+ for (int byteIndex = 0; byteIndex < blockSize; byteIndex++)
+ {
+ xorResult[byteIndex] = (byte)(c[byteIndex] ^ input[byteIndex]);
+ }
+ }
+#else
+ private void ProcessBlock(byte[] input, int inOff)
{
Xor(c, 0, input, inOff, cTemp);
engine.ProcessBlock(cTemp, 0, c, 0);
}
+#endif
private void Xor(byte[] c, int cOff, byte[] input, int inOff, byte[] xorResult)
- {
- for (int byteIndex = 0; byteIndex < blockSize; byteIndex++)
- {
- xorResult[byteIndex] = (byte)(c[byteIndex + cOff] ^ input[byteIndex + inOff]);
- }
- }
-
- public int DoFinal(byte[] output, int outOff)
- {
- if (bufOff % buf.Length != 0)
+ {
+ for (int byteIndex = 0; byteIndex < blockSize; byteIndex++)
{
- throw new DataLengthException("Input must be a multiple of blocksize");
+ xorResult[byteIndex] = (byte)(c[byteIndex + cOff] ^ input[byteIndex + inOff]);
}
+ }
+
+ public int DoFinal(byte[] output, int outOff)
+ {
+ if (bufOff % buf.Length != 0)
+ throw new DataLengthException("Input must be a multiple of blocksize");
//Last block
Xor(c, 0, buf, 0, cTemp);
@@ -137,17 +183,15 @@ namespace Org.BouncyCastle.Crypto.Macs
engine.ProcessBlock(c, 0, c, 0);
if (macSize + outOff > output.Length)
- {
throw new DataLengthException("Output buffer too short");
- }
Array.Copy(c, 0, output, outOff, macSize);
return macSize;
}
- public void Reset()
- {
+ public void Reset()
+ {
Arrays.Fill(c, (byte)0x00);
Arrays.Fill(cTemp, (byte)0x00);
Arrays.Fill(kDelta, (byte)0x00);
@@ -156,5 +200,5 @@ namespace Org.BouncyCastle.Crypto.Macs
engine.ProcessBlock(kDelta, 0, kDelta, 0);
bufOff = 0;
}
- }
+ }
}
diff --git a/crypto/src/crypto/macs/GMac.cs b/crypto/src/crypto/macs/GMac.cs
index 0554c44f0..804097b3b 100644
--- a/crypto/src/crypto/macs/GMac.cs
+++ b/crypto/src/crypto/macs/GMac.cs
@@ -52,10 +52,8 @@ namespace Org.BouncyCastle.Crypto.Macs
/// </summary>
public void Init(ICipherParameters parameters)
{
- if (parameters is ParametersWithIV)
+ if (parameters is ParametersWithIV param)
{
- ParametersWithIV param = (ParametersWithIV)parameters;
-
byte[] iv = param.GetIV();
KeyParameter keyParam = (KeyParameter)param.Parameters;
@@ -88,6 +86,22 @@ namespace Org.BouncyCastle.Crypto.Macs
cipher.ProcessAadBytes(input, inOff, len);
}
+#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);
+ }
+#endif
+
public int DoFinal(byte[] output, int outOff)
{
try
diff --git a/crypto/src/crypto/macs/GOST28147Mac.cs b/crypto/src/crypto/macs/GOST28147Mac.cs
index 33c2d67ee..6a6907934 100644
--- a/crypto/src/crypto/macs/GOST28147Mac.cs
+++ b/crypto/src/crypto/macs/GOST28147Mac.cs
@@ -1,7 +1,7 @@
using System;
-using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Macs
@@ -9,10 +9,11 @@ namespace Org.BouncyCastle.Crypto.Macs
/**
* implementation of GOST 28147-89 MAC
*/
- public class Gost28147Mac : IMac
+ public class Gost28147Mac
+ : IMac
{
- private const int blockSize = 8;
- private const int macSize = 4;
+ private const int BlockSize = 8;
+ private const int MacSize = 4;
private int bufOff;
private byte[] buf;
private byte[] mac;
@@ -36,8 +37,8 @@ namespace Org.BouncyCastle.Crypto.Macs
public Gost28147Mac()
{
- mac = new byte[blockSize];
- buf = new byte[blockSize];
+ mac = new byte[BlockSize];
+ buf = new byte[BlockSize];
bufOff = 0;
}
@@ -50,22 +51,19 @@ namespace Org.BouncyCastle.Crypto.Macs
int[] key = new int[8];
for(int i=0; i!=8; i++)
{
- key[i] = bytesToint(userKey,i*4);
+ key[i] = (int)Pack.LE_To_UInt32(userKey, i * 4);
}
return key;
}
- public void Init(
- ICipherParameters parameters)
+ public void Init(ICipherParameters parameters)
{
Reset();
- buf = new byte[blockSize];
+ buf = new byte[BlockSize];
macIV = null;
- if (parameters is ParametersWithSBox)
+ if (parameters is ParametersWithSBox param)
{
- ParametersWithSBox param = (ParametersWithSBox)parameters;
-
//
// Set the S-Box
//
@@ -79,17 +77,15 @@ namespace Org.BouncyCastle.Crypto.Macs
workingKey = GenerateWorkingKey(((KeyParameter)param.Parameters).GetKey());
}
}
- else if (parameters is KeyParameter)
+ else if (parameters is KeyParameter keyParameter)
{
- workingKey = GenerateWorkingKey(((KeyParameter)parameters).GetKey());
+ workingKey = GenerateWorkingKey(keyParameter.GetKey());
}
- else if (parameters is ParametersWithIV)
+ else if (parameters is ParametersWithIV ivParam)
{
- ParametersWithIV p = (ParametersWithIV)parameters;
-
- workingKey = GenerateWorkingKey(((KeyParameter)p.Parameters).GetKey());
- Array.Copy(p.GetIV(), 0, mac, 0, mac.Length);
- macIV = p.GetIV(); // don't skip the initial CM5Func
+ workingKey = GenerateWorkingKey(((KeyParameter)ivParam.Parameters).GetKey());
+ macIV = ivParam.GetIV(); // don't skip the initial CM5Func
+ Array.Copy(macIV, 0, mac, 0, mac.Length);
}
else
{
@@ -105,10 +101,10 @@ namespace Org.BouncyCastle.Crypto.Macs
public int GetMacSize()
{
- return macSize;
+ return MacSize;
}
- private int gost28147_mainStep(int n1, int key)
+ private int Gost28147_mainStep(int n1, int key)
{
int cm = (key + n1); // CM1
@@ -130,177 +126,187 @@ namespace Org.BouncyCastle.Crypto.Macs
return omLeft | omRight;
}
- private void gost28147MacFunc(
+ private void Gost28147MacFunc(
int[] workingKey,
byte[] input,
int inOff,
byte[] output,
int outOff)
{
- int N1, N2, tmp; //tmp -> for saving N1
- N1 = bytesToint(input, inOff);
- N2 = bytesToint(input, inOff + 4);
+ int N1 = (int)Pack.LE_To_UInt32(input, inOff);
+ int N2 = (int)Pack.LE_To_UInt32(input, inOff + 4);
+ int tmp; //tmp -> for saving N1
for (int k = 0; k < 2; k++) // 1-16 steps
{
for (int j = 0; j < 8; j++)
{
tmp = N1;
- N1 = N2 ^ gost28147_mainStep(N1, workingKey[j]); // CM2
+ N1 = N2 ^ Gost28147_mainStep(N1, workingKey[j]); // CM2
N2 = tmp;
}
}
- intTobytes(N1, output, outOff);
- intTobytes(N2, output, outOff + 4);
- }
-
- //array of bytes to type int
- private static int bytesToint(
- byte[] input,
- int inOff)
- {
- return (int)((input[inOff + 3] << 24) & 0xff000000) + ((input[inOff + 2] << 16) & 0xff0000)
- + ((input[inOff + 1] << 8) & 0xff00) + (input[inOff] & 0xff);
- }
-
- //int to array of bytes
- private static void intTobytes(
- int num,
- byte[] output,
- int outOff)
- {
- output[outOff + 3] = (byte)(num >> 24);
- output[outOff + 2] = (byte)(num >> 16);
- output[outOff + 1] = (byte)(num >> 8);
- output[outOff] = (byte)num;
- }
-
- private static byte[] CM5func(
- byte[] buf,
- int bufOff,
- byte[] mac)
- {
- byte[] sum = new byte[buf.Length - bufOff];
-
- Array.Copy(buf, bufOff, sum, 0, mac.Length);
-
- for (int i = 0; i != mac.Length; i++)
- {
- sum[i] = (byte)(sum[i] ^ mac[i]);
- }
-
- return sum;
+ Pack.UInt32_To_LE((uint)N1, output, outOff);
+ Pack.UInt32_To_LE((uint)N2, output, outOff + 4);
}
- public void Update(
- byte input)
+ public void Update(byte input)
{
if (bufOff == buf.Length)
{
- byte[] sumbuf = new byte[buf.Length];
- Array.Copy(buf, 0, sumbuf, 0, mac.Length);
-
+ byte[] sum = new byte[buf.Length];
if (firstStep)
{
firstStep = false;
if (macIV != null)
{
- sumbuf = CM5func(buf, 0, macIV);
+ Cm5Func(buf, 0, macIV, sum);
}
- }
+ else
+ {
+ Array.Copy(buf, 0, sum, 0, mac.Length);
+ }
+ }
else
{
- sumbuf = CM5func(buf, 0, mac);
+ Cm5Func(buf, 0, mac, sum);
}
- gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
+ Gost28147MacFunc(workingKey, sum, 0, mac, 0);
bufOff = 0;
}
buf[bufOff++] = input;
}
- public void BlockUpdate(
- byte[] input,
- int inOff,
- int len)
+ public void BlockUpdate(byte[] input, int inOff, int len)
{
if (len < 0)
throw new ArgumentException("Can't have a negative input length!");
- int gapLen = blockSize - bufOff;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ BlockUpdate(input.AsSpan(inOff, len));
+#else
+ int gapLen = BlockSize - bufOff;
if (len > gapLen)
{
Array.Copy(input, inOff, buf, bufOff, gapLen);
- byte[] sumbuf = new byte[buf.Length];
- Array.Copy(buf, 0, sumbuf, 0, mac.Length);
-
+ byte[] sum = new byte[buf.Length];
if (firstStep)
{
firstStep = false;
if (macIV != null)
{
- sumbuf = CM5func(buf, 0, macIV);
+ Cm5Func(buf, 0, macIV, sum);
}
- }
+ else
+ {
+ Array.Copy(buf, 0, sum, 0, mac.Length);
+ }
+ }
else
{
- sumbuf = CM5func(buf, 0, mac);
+ Cm5Func(buf, 0, mac, sum);
}
- gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
+ Gost28147MacFunc(workingKey, sum, 0, mac, 0);
bufOff = 0;
len -= gapLen;
inOff += gapLen;
- while (len > blockSize)
+ while (len > BlockSize)
{
- sumbuf = CM5func(input, inOff, mac);
- gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
+ Cm5Func(input, inOff, mac, sum);
+ Gost28147MacFunc(workingKey, sum, 0, mac, 0);
- len -= blockSize;
- inOff += blockSize;
+ len -= BlockSize;
+ inOff += BlockSize;
}
}
Array.Copy(input, inOff, buf, bufOff, len);
bufOff += len;
+#endif
}
- public int DoFinal(
- byte[] output,
- int outOff)
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void BlockUpdate(ReadOnlySpan<byte> input)
+ {
+ int gapLen = BlockSize - bufOff;
+
+ if (input.Length > gapLen)
+ {
+ input[..gapLen].CopyTo(buf.AsSpan(bufOff));
+
+ byte[] sum = new byte[buf.Length];
+ if (firstStep)
+ {
+ firstStep = false;
+ if (macIV != null)
+ {
+ Cm5Func(buf, macIV, sum);
+ }
+ else
+ {
+ Array.Copy(buf, 0, sum, 0, mac.Length);
+ }
+ }
+ else
+ {
+ Cm5Func(buf, mac, sum);
+ }
+
+ Gost28147MacFunc(workingKey, sum, 0, mac, 0);
+
+ bufOff = 0;
+ input = input[gapLen..];
+
+ while (input.Length > BlockSize)
+ {
+ Cm5Func(input, mac, sum);
+ Gost28147MacFunc(workingKey, sum, 0, mac, 0);
+
+ input = input[BlockSize..];
+ }
+ }
+
+ input.CopyTo(buf.AsSpan(bufOff));
+
+ bufOff += input.Length;
+ }
+#endif
+
+ public int DoFinal(byte[] output, int outOff)
{
//padding with zero
- while (bufOff < blockSize)
+ while (bufOff < BlockSize)
{
buf[bufOff++] = 0;
}
- byte[] sumbuf = new byte[buf.Length];
- Array.Copy(buf, 0, sumbuf, 0, mac.Length);
-
+ byte[] sum = new byte[buf.Length];
if (firstStep)
{
firstStep = false;
+ Array.Copy(buf, 0, sum, 0, mac.Length);
}
else
{
- sumbuf = CM5func(buf, 0, mac);
+ Cm5Func(buf, 0, mac, sum);
}
- gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
+ Gost28147MacFunc(workingKey, sum, 0, mac, 0);
- Array.Copy(mac, (mac.Length/2)-macSize, output, outOff, macSize);
+ Array.Copy(mac, (mac.Length/2)-MacSize, output, outOff, MacSize);
Reset();
- return macSize;
+ return MacSize;
}
public void Reset()
@@ -311,5 +317,23 @@ namespace Org.BouncyCastle.Crypto.Macs
firstStep = true;
}
+
+ private static void Cm5Func(byte[] buf, int bufOff, byte[] mac, byte[] sum)
+ {
+ for (int i = 0; i < BlockSize; ++i)
+ {
+ sum[i] = (byte)(buf[bufOff + i] ^ mac[i]);
+ }
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ private static void Cm5Func(ReadOnlySpan<byte> buffer, ReadOnlySpan<byte> mac, Span<byte> sum)
+ {
+ for (int i = 0; i < BlockSize; ++i)
+ {
+ sum[i] = (byte)(buffer[i] ^ mac[i]);
+ }
+ }
+#endif
}
}
diff --git a/crypto/src/crypto/macs/HMac.cs b/crypto/src/crypto/macs/HMac.cs
index a717ce4f7..389c03a23 100644
--- a/crypto/src/crypto/macs/HMac.cs
+++ b/crypto/src/crypto/macs/HMac.cs
@@ -99,6 +99,13 @@ namespace Org.BouncyCastle.Crypto.Macs
digest.BlockUpdate(input, inOff, len);
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public virtual void BlockUpdate(ReadOnlySpan<byte> input)
+ {
+ digest.BlockUpdate(input);
+ }
+#endif
+
public virtual int DoFinal(byte[] output, int outOff)
{
digest.DoFinal(outputBuf, blockLength);
diff --git a/crypto/src/crypto/macs/ISO9797Alg3Mac.cs b/crypto/src/crypto/macs/ISO9797Alg3Mac.cs
index 6fee619c1..f516e9b96 100644
--- a/crypto/src/crypto/macs/ISO9797Alg3Mac.cs
+++ b/crypto/src/crypto/macs/ISO9797Alg3Mac.cs
@@ -180,14 +180,14 @@ namespace Org.BouncyCastle.Crypto.Macs
buf[bufOff++] = input;
}
- public void BlockUpdate(
- byte[] input,
- int inOff,
- int len)
+ public void BlockUpdate(byte[] input, int inOff, int len)
{
if (len < 0)
throw new ArgumentException("Can't have a negative input length!");
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ BlockUpdate(input.AsSpan(inOff, len));
+#else
int blockSize = cipher.GetBlockSize();
int resultLen = 0;
int gapLen = blockSize - bufOff;
@@ -214,8 +214,38 @@ namespace Org.BouncyCastle.Crypto.Macs
Array.Copy(input, inOff, buf, bufOff, len);
bufOff += len;
+#endif
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void BlockUpdate(ReadOnlySpan<byte> input)
+ {
+ int blockSize = cipher.GetBlockSize();
+ int resultLen = 0;
+ int gapLen = blockSize - bufOff;
+
+ if (input.Length > gapLen)
+ {
+ input[..gapLen].CopyTo(buf.AsSpan(bufOff));
+
+ resultLen += cipher.ProcessBlock(buf, mac);
+
+ bufOff = 0;
+ input = input[gapLen..];
+
+ while (input.Length > blockSize)
+ {
+ resultLen += cipher.ProcessBlock(input, mac);
+ input = input[blockSize..];
+ }
+ }
+
+ input.CopyTo(buf.AsSpan(bufOff));
+
+ bufOff += input.Length;
+ }
+#endif
+
public int DoFinal(
byte[] output,
int outOff)
diff --git a/crypto/src/crypto/macs/Poly1305.cs b/crypto/src/crypto/macs/Poly1305.cs
index 595d9b051..65fb8bf01 100644
--- a/crypto/src/crypto/macs/Poly1305.cs
+++ b/crypto/src/crypto/macs/Poly1305.cs
@@ -167,15 +167,22 @@ namespace Org.BouncyCastle.Crypto.Macs
currentBlock[currentBlockOffset++] = input;
if (currentBlockOffset == BlockSize)
{
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ ProcessBlock(currentBlock);
+#else
ProcessBlock(currentBlock, 0);
+#endif
currentBlockOffset = 0;
}
}
public void BlockUpdate(byte[] input, int inOff, int len)
{
- // TODO Validity check on arguments
+ Check.DataLength(input, inOff, len, "input buffer too short");
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ BlockUpdate(input.AsSpan(inOff, len));
+#else
int available = BlockSize - currentBlockOffset;
if (len < available)
{
@@ -189,37 +196,108 @@ namespace Org.BouncyCastle.Crypto.Macs
{
Array.Copy(input, inOff, currentBlock, currentBlockOffset, available);
pos = available;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ ProcessBlock(currentBlock);
+#else
ProcessBlock(currentBlock, 0);
+#endif
}
int remaining;
while ((remaining = len - pos) >= BlockSize)
{
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ ProcessBlock(input.AsSpan(inOff + pos));
+#else
ProcessBlock(input, inOff + pos);
+#endif
pos += BlockSize;
}
Array.Copy(input, inOff + pos, currentBlock, 0, remaining);
currentBlockOffset = remaining;
+#endif
}
- private void ProcessBlock(byte[] buf, int off)
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void BlockUpdate(ReadOnlySpan<byte> input)
+ {
+ int available = BlockSize - currentBlockOffset;
+ if (input.Length < available)
+ {
+ input.CopyTo(currentBlock.AsSpan(currentBlockOffset));
+ currentBlockOffset += input.Length;
+ return;
+ }
+
+ int pos = 0;
+ if (currentBlockOffset > 0)
+ {
+ input[..available].CopyTo(currentBlock.AsSpan(currentBlockOffset));
+ pos = available;
+ ProcessBlock(currentBlock);
+ }
+
+ int remaining;
+ while ((remaining = input.Length - pos) >= BlockSize)
+ {
+ ProcessBlock(input[pos..]);
+ pos += BlockSize;
+ }
+
+ input[pos..].CopyTo(currentBlock);
+ currentBlockOffset = remaining;
+ }
+#endif
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ private void ProcessBlock(ReadOnlySpan<byte> block)
{
#if NETCOREAPP3_0_OR_GREATER
if (BitConverter.IsLittleEndian)
{
Span<uint> t = stackalloc uint[4];
- Unsafe.CopyBlockUnaligned(ref Unsafe.As<uint, byte>(ref t[0]), ref buf[off], 16);
+ Unsafe.CopyBlockUnaligned(ref Unsafe.As<uint, byte>(ref t[0]), ref Unsafe.AsRef(block[0]), 16);
h0 += t[0] & 0x3ffffffU;
h1 += ((t[1] << 6) | (t[0] >> 26)) & 0x3ffffffU;
h2 += ((t[2] << 12) | (t[1] >> 20)) & 0x3ffffffU;
h3 += ((t[3] << 18) | (t[2] >> 14)) & 0x3ffffffU;
- h4 += (1 << 24) | (t[3] >> 8);
+ h4 += (1 << 24) | (t[3] >> 8);
}
else
#endif
{
+ uint t0 = Pack.LE_To_UInt32(block);
+ uint t1 = Pack.LE_To_UInt32(block[4..]);
+ uint t2 = Pack.LE_To_UInt32(block[8..]);
+ uint t3 = Pack.LE_To_UInt32(block[12..]);
+
+ h0 += t0 & 0x3ffffffU;
+ h1 += ((t1 << 6) | (t0 >> 26)) & 0x3ffffffU;
+ h2 += ((t2 << 12) | (t1 >> 20)) & 0x3ffffffU;
+ h3 += ((t3 << 18) | (t2 >> 14)) & 0x3ffffffU;
+ h4 += ( 1 << 24) | (t3 >> 8);
+ }
+
+ ulong tp0 = (ulong)h0 * r0 + (ulong)h1 * s4 + (ulong)h2 * s3 + (ulong)h3 * s2 + (ulong)h4 * s1;
+ ulong tp1 = (ulong)h0 * r1 + (ulong)h1 * r0 + (ulong)h2 * s4 + (ulong)h3 * s3 + (ulong)h4 * s2;
+ ulong tp2 = (ulong)h0 * r2 + (ulong)h1 * r1 + (ulong)h2 * r0 + (ulong)h3 * s4 + (ulong)h4 * s3;
+ ulong tp3 = (ulong)h0 * r3 + (ulong)h1 * r2 + (ulong)h2 * r1 + (ulong)h3 * r0 + (ulong)h4 * s4;
+ ulong tp4 = (ulong)h0 * r4 + (ulong)h1 * r3 + (ulong)h2 * r2 + (ulong)h3 * r1 + (ulong)h4 * r0;
+
+ h0 = (uint)tp0 & 0x3ffffff; tp1 += (tp0 >> 26);
+ h1 = (uint)tp1 & 0x3ffffff; tp2 += (tp1 >> 26);
+ h2 = (uint)tp2 & 0x3ffffff; tp3 += (tp2 >> 26);
+ h3 = (uint)tp3 & 0x3ffffff; tp4 += (tp3 >> 26);
+ h4 = (uint)tp4 & 0x3ffffff;
+ h0 += (uint)(tp4 >> 26) * 5;
+ h1 += h0 >> 26; h0 &= 0x3ffffff;
+ }
+#else
+ private void ProcessBlock(byte[] buf, int off)
+ {
+ {
uint t0 = Pack.LE_To_UInt32(buf, off + 0);
uint t1 = Pack.LE_To_UInt32(buf, off + 4);
uint t2 = Pack.LE_To_UInt32(buf, off + 8);
@@ -246,10 +324,11 @@ namespace Org.BouncyCastle.Crypto.Macs
h0 += (uint)(tp4 >> 26) * 5;
h1 += h0 >> 26; h0 &= 0x3ffffff;
}
+#endif
public int DoFinal(byte[] output, int outOff)
{
- Check.DataLength(output, outOff, BlockSize, "Output buffer is too short.");
+ Check.DataLength(output, outOff, BlockSize, "output buffer is too short.");
if (currentBlockOffset > 0)
{
@@ -265,7 +344,11 @@ namespace Org.BouncyCastle.Crypto.Macs
h4 -= (1 << 24);
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ ProcessBlock(currentBlock);
+#else
ProcessBlock(currentBlock, 0);
+#endif
}
Debug.Assert(h4 >> 26 == 0);
diff --git a/crypto/src/crypto/macs/SipHash.cs b/crypto/src/crypto/macs/SipHash.cs
index e1a19fa5b..fc0a66ed1 100644
--- a/crypto/src/crypto/macs/SipHash.cs
+++ b/crypto/src/crypto/macs/SipHash.cs
@@ -80,6 +80,9 @@ namespace Org.BouncyCastle.Crypto.Macs
public virtual void BlockUpdate(byte[] input, int offset, int length)
{
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ BlockUpdate(input.AsSpan(offset, length));
+#else
int i = 0, fullWords = length & ~7;
if (wordPos == 0)
{
@@ -115,8 +118,51 @@ namespace Org.BouncyCastle.Crypto.Macs
}
}
}
+#endif
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public virtual void BlockUpdate(ReadOnlySpan<byte> input)
+ {
+ int length = input.Length;
+ int i = 0, fullWords = length & ~7;
+ if (wordPos == 0)
+ {
+ for (; i < fullWords; i += 8)
+ {
+ m = (long)Pack.LE_To_UInt64(input[i..]);
+ ProcessMessageWord();
+ }
+ for (; i < length; ++i)
+ {
+ m = (long)(((ulong)m >> 8) | ((ulong)input[i] << 56));
+ }
+ wordPos = length - fullWords;
+ }
+ else
+ {
+ int bits = wordPos << 3;
+ for (; i < fullWords; i += 8)
+ {
+ ulong n = Pack.LE_To_UInt64(input[i..]);
+ m = (long)((n << bits) | ((ulong)m >> -bits));
+ ProcessMessageWord();
+ m = (long)n;
+ }
+ for (; i < length; ++i)
+ {
+ m = (long)(((ulong)m >> 8) | ((ulong)input[i] << 56));
+
+ if (++wordPos == 8)
+ {
+ ProcessMessageWord();
+ wordPos = 0;
+ }
+ }
+ }
+ }
+#endif
+
public virtual long DoFinal()
{
// NOTE: 2 distinct shifts to avoid "64-bit shift" when wordPos == 0
diff --git a/crypto/src/crypto/macs/SkeinMac.cs b/crypto/src/crypto/macs/SkeinMac.cs
index 07eff24f4..6adc93ef9 100644
--- a/crypto/src/crypto/macs/SkeinMac.cs
+++ b/crypto/src/crypto/macs/SkeinMac.cs
@@ -106,13 +106,19 @@ namespace Org.BouncyCastle.Crypto.Macs
public void BlockUpdate(byte[] input, int inOff, int len)
{
- engine.Update(input, inOff, len);
+ engine.BlockUpdate(input, inOff, len);
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void BlockUpdate(ReadOnlySpan<byte> input)
+ {
+ engine.BlockUpdate(input);
+ }
+#endif
+
public int DoFinal(byte[] output, int outOff)
{
return engine.DoFinal(output, outOff);
}
-
}
}
diff --git a/crypto/src/crypto/macs/VMPCMac.cs b/crypto/src/crypto/macs/VMPCMac.cs
index 6f2da075c..76912f736 100644
--- a/crypto/src/crypto/macs/VMPCMac.cs
+++ b/crypto/src/crypto/macs/VMPCMac.cs
@@ -159,15 +159,24 @@ namespace Org.BouncyCastle.Crypto.Macs
n = (byte) ((n + 1) & 0xff);
}
- public virtual void BlockUpdate(byte[] input, int inOff, int len)
+ public virtual void BlockUpdate(byte[] input, int inOff, int inLen)
{
- if ((inOff + len) > input.Length)
- throw new DataLengthException("input buffer too short");
+ Check.DataLength(input, inOff, inLen, "input buffer too short");
- for (int i = 0; i < len; i++)
+ for (int i = 0; i < inLen; i++)
{
Update(input[inOff + i]);
}
}
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public virtual void BlockUpdate(ReadOnlySpan<byte> input)
+ {
+ for (int i = 0; i < input.Length; i++)
+ {
+ Update(input[i]);
+ }
+ }
+#endif
}
}
|