diff --git a/crypto/src/cms/CMSEnvelopedHelper.cs b/crypto/src/cms/CMSEnvelopedHelper.cs
index 40c5e6868..c623ec677 100644
--- a/crypto/src/cms/CMSEnvelopedHelper.cs
+++ b/crypto/src/cms/CMSEnvelopedHelper.cs
@@ -1,4 +1,7 @@
using System;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+using System.Buffers;
+#endif
using System.Collections.Generic;
using System.IO;
@@ -240,7 +243,12 @@ namespace Org.BouncyCastle.Cms
|| alg.Equals(CmsEnvelopedGenerator.IdeaCbc)
|| alg.Equals(CmsEnvelopedGenerator.Cast5Cbc))
{
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ cipherParameters = ParametersWithIV.Create<byte>(cipherParameters, 8, 0,
+ (bytes, state) => bytes.Fill(state));
+#else
cipherParameters = new ParametersWithIV(cipherParameters, new byte[8]);
+#endif
}
}
diff --git a/crypto/src/cms/PasswordRecipientInfoGenerator.cs b/crypto/src/cms/PasswordRecipientInfoGenerator.cs
index 5bbf8f727..1243bea9f 100644
--- a/crypto/src/cms/PasswordRecipientInfoGenerator.cs
+++ b/crypto/src/cms/PasswordRecipientInfoGenerator.cs
@@ -48,17 +48,29 @@ namespace Org.BouncyCastle.Cms
// Note: In Java build, the IV is automatically generated in JCE layer
int ivLength = Platform.StartsWithIgnoreCase(rfc3211WrapperName, "DES") ? 8 : 16;
- byte[] iv = new byte[ivLength];
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ var parametersWithIV = ParametersWithIV.Create(keyEncryptionKey, ivLength, random,
+ (bytes, random) => random.NextBytes(bytes));
+#else
+ byte[] iv = new byte[ivLength];
random.NextBytes(iv);
- ICipherParameters parameters = new ParametersWithIV(keyEncryptionKey, iv);
- keyWrapper.Init(true, new ParametersWithRandom(parameters, random));
+ var parametersWithIV = new ParametersWithIV(keyEncryptionKey, iv);
+#endif
+
+ keyWrapper.Init(true, new ParametersWithRandom(parametersWithIV, random));
Asn1OctetString encryptedKey = new DerOctetString(
keyWrapper.Wrap(keyBytes, 0, keyBytes.Length));
DerSequence seq = new DerSequence(
new DerObjectIdentifier(keyEncryptionKeyOID),
- new DerOctetString(iv));
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ new DerOctetString(parametersWithIV.IV)
+#else
+ new DerOctetString(iv)
+#endif
+ );
AlgorithmIdentifier keyEncryptionAlgorithm = new AlgorithmIdentifier(
PkcsObjectIdentifiers.IdAlgPwriKek, seq);
diff --git a/crypto/src/cms/PasswordRecipientInformation.cs b/crypto/src/cms/PasswordRecipientInformation.cs
index f629caba6..ff4a20d68 100644
--- a/crypto/src/cms/PasswordRecipientInformation.cs
+++ b/crypto/src/cms/PasswordRecipientInformation.cs
@@ -54,12 +54,17 @@ namespace Org.BouncyCastle.Cms
string cName = CmsEnvelopedHelper.Instance.GetRfc3211WrapperName(kekAlgName);
IWrapper keyWrapper = WrapperUtilities.GetWrapper(cName);
- byte[] iv = Asn1OctetString.GetInstance(kekAlgParams[1]).GetOctets();
+ var iv = Asn1OctetString.GetInstance(kekAlgParams[1]);
- ICipherParameters parameters = ((CmsPbeKey)key).GetEncoded(kekAlgName);
- parameters = new ParametersWithIV(parameters, iv);
+ ICipherParameters parameters = ((CmsPbeKey)key).GetEncoded(kekAlgName);
- keyWrapper.Init(false, parameters);
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ parameters = new ParametersWithIV(parameters, iv.GetOctetsSpan());
+#else
+ parameters = new ParametersWithIV(parameters, iv.GetOctets());
+#endif
+
+ keyWrapper.Init(false, parameters);
KeyParameter sKey = ParameterUtilities.CreateKeyParameter(
GetContentAlgorithmName(), keyWrapper.Unwrap(encryptedKey, 0, encryptedKey.Length));
diff --git a/crypto/src/crypto/engines/AsconEngine.cs b/crypto/src/crypto/engines/AsconEngine.cs
index 3ca5ede60..4bda8a02a 100644
--- a/crypto/src/crypto/engines/AsconEngine.cs
+++ b/crypto/src/crypto/engines/AsconEngine.cs
@@ -114,12 +114,20 @@ namespace Org.BouncyCastle.Crypto.Engines
public void Init(bool forEncryption, ICipherParameters parameters)
{
KeyParameter key;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ ReadOnlySpan<byte> npub;
+#else
byte[] npub;
+#endif
if (parameters is AeadParameters aeadParameters)
{
key = aeadParameters.Key;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ npub = aeadParameters.Nonce;
+#else
npub = aeadParameters.GetNonce();
+#endif
initialAssociatedText = aeadParameters.GetAssociatedText();
int macSizeBits = aeadParameters.MacSize;
@@ -129,7 +137,11 @@ namespace Org.BouncyCastle.Crypto.Engines
else if (parameters is ParametersWithIV withIV)
{
key = withIV.Parameters as KeyParameter;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ npub = withIV.IV;
+#else
npub = withIV.GetIV();
+#endif
initialAssociatedText = null;
}
else
@@ -139,7 +151,7 @@ namespace Org.BouncyCastle.Crypto.Engines
if (key == null)
throw new ArgumentException("Ascon Init parameters must include a key");
- if (npub == null || npub.Length != CRYPTO_ABYTES)
+ if (npub.Length != CRYPTO_ABYTES)
throw new ArgumentException(asconParameters + " requires exactly " + CRYPTO_ABYTES + " bytes of IV");
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
@@ -156,25 +168,14 @@ namespace Org.BouncyCastle.Crypto.Engines
if (CRYPTO_KEYBYTES == 16)
{
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- K1 = Pack.BE_To_UInt64(k);
- K2 = Pack.BE_To_UInt64(k[8..]);
-#else
K1 = Pack.BE_To_UInt64(k, 0);
K2 = Pack.BE_To_UInt64(k, 8);
-#endif
}
else if (CRYPTO_KEYBYTES == 20)
{
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- K0 = Pack.BE_To_UInt32(k);
- K1 = Pack.BE_To_UInt64(k[4..]);
- K2 = Pack.BE_To_UInt64(k[12..]);
-#else
K0 = Pack.BE_To_UInt32(k, 0);
K1 = Pack.BE_To_UInt64(k, 4);
K2 = Pack.BE_To_UInt64(k, 12);
-#endif
}
else
{
diff --git a/crypto/src/crypto/modes/CcmBlockCipher.cs b/crypto/src/crypto/modes/CcmBlockCipher.cs
index 7784e7cca..b7d90298a 100644
--- a/crypto/src/crypto/modes/CcmBlockCipher.cs
+++ b/crypto/src/crypto/modes/CcmBlockCipher.cs
@@ -81,7 +81,7 @@ namespace Org.BouncyCastle.Crypto.Modes
keyParam = cipherParameters;
}
- if (nonce == null || nonce.Length < 7 || nonce.Length > 13)
+ if (nonce.Length < 7 || nonce.Length > 13)
throw new ArgumentException("nonce must have length from 7 to 13 octets");
Reset();
diff --git a/crypto/src/crypto/modes/ChaCha20Poly1305.cs b/crypto/src/crypto/modes/ChaCha20Poly1305.cs
index 01bf6ccb8..56bef5e93 100644
--- a/crypto/src/crypto/modes/ChaCha20Poly1305.cs
+++ b/crypto/src/crypto/modes/ChaCha20Poly1305.cs
@@ -72,7 +72,11 @@ namespace Org.BouncyCastle.Crypto.Modes
public virtual void Init(bool forEncryption, ICipherParameters parameters)
{
KeyParameter initKeyParam;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ ReadOnlySpan<byte> initNonce;
+#else
byte[] initNonce;
+#endif
ICipherParameters chacha20Params;
if (parameters is AeadParameters aeadParams)
@@ -82,7 +86,11 @@ namespace Org.BouncyCastle.Crypto.Modes
throw new ArgumentException("Invalid value for MAC size: " + macSizeBits);
initKeyParam = aeadParams.Key;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ initNonce = aeadParams.Nonce;
+#else
initNonce = aeadParams.GetNonce();
+#endif
chacha20Params = new ParametersWithIV(initKeyParam, initNonce);
this.mInitialAad = aeadParams.GetAssociatedText();
@@ -90,7 +98,11 @@ namespace Org.BouncyCastle.Crypto.Modes
else if (parameters is ParametersWithIV ivParams)
{
initKeyParam = (KeyParameter)ivParams.Parameters;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ initNonce = ivParams.IV;
+#else
initNonce = ivParams.GetIV();
+#endif
chacha20Params = ivParams;
this.mInitialAad = null;
@@ -113,11 +125,15 @@ namespace Org.BouncyCastle.Crypto.Modes
}
// Validate nonce
- if (null == initNonce || NonceSize != initNonce.Length)
+ if (NonceSize != initNonce.Length)
throw new ArgumentException("Nonce must be 96 bits");
// Check for encryption with reused nonce
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ if (State.Uninitialized != mState && forEncryption && initNonce.SequenceEqual(mNonce))
+#else
if (State.Uninitialized != mState && forEncryption && Arrays.AreEqual(mNonce, initNonce))
+#endif
{
if (null == initKeyParam || initKeyParam.FixedTimeEquals(mKey))
throw new ArgumentException("cannot reuse nonce for ChaCha20Poly1305 encryption");
@@ -128,7 +144,11 @@ namespace Org.BouncyCastle.Crypto.Modes
initKeyParam.CopyTo(mKey, 0, KeySize);
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ initNonce.CopyTo(mNonce);
+#else
Array.Copy(initNonce, 0, mNonce, 0, NonceSize);
+#endif
mChacha20.Init(true, chacha20Params);
diff --git a/crypto/src/crypto/modes/EAXBlockCipher.cs b/crypto/src/crypto/modes/EAXBlockCipher.cs
index 3b95cd7f2..858786d10 100644
--- a/crypto/src/crypto/modes/EAXBlockCipher.cs
+++ b/crypto/src/crypto/modes/EAXBlockCipher.cs
@@ -72,19 +72,31 @@ namespace Org.BouncyCastle.Crypto.Modes
{
this.forEncryption = forEncryption;
- byte[] nonce;
- ICipherParameters keyParam;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ ReadOnlySpan<byte> nonce;
+#else
+ byte[] nonce;
+#endif
+ ICipherParameters keyParam;
if (parameters is AeadParameters aeadParameters)
{
- nonce = aeadParameters.GetNonce();
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ nonce = aeadParameters.Nonce;
+#else
+ nonce = aeadParameters.GetNonce();
+#endif
initialAssociatedText = aeadParameters.GetAssociatedText();
macSize = aeadParameters.MacSize / 8;
keyParam = aeadParameters.Key;
}
else if (parameters is ParametersWithIV parametersWithIV)
{
- nonce = parametersWithIV.GetIV();
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ nonce = parametersWithIV.IV;
+#else
+ nonce = parametersWithIV.GetIV();
+#endif
initialAssociatedText = null;
macSize = mac.GetMacSize() / 2;
keyParam = parametersWithIV.Parameters;
@@ -103,7 +115,11 @@ namespace Org.BouncyCastle.Crypto.Modes
tag[blockSize - 1] = (byte)Tag.N;
mac.BlockUpdate(tag, 0, blockSize);
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ mac.BlockUpdate(nonce);
+#else
mac.BlockUpdate(nonce, 0, nonce.Length);
+#endif
mac.DoFinal(nonceMac, 0);
// Same BlockCipher underlies this and the mac, so reuse last key on cipher
diff --git a/crypto/src/crypto/modes/GCMBlockCipher.cs b/crypto/src/crypto/modes/GCMBlockCipher.cs
index fef980091..c592c3af3 100644
--- a/crypto/src/crypto/modes/GCMBlockCipher.cs
+++ b/crypto/src/crypto/modes/GCMBlockCipher.cs
@@ -117,11 +117,19 @@ namespace Org.BouncyCastle.Crypto.Modes
this.initialised = true;
KeyParameter keyParam;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ ReadOnlySpan<byte> newNonce;
+#else
byte[] newNonce;
+#endif
if (parameters is AeadParameters aeadParameters)
{
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ newNonce = aeadParameters.Nonce;
+#else
newNonce = aeadParameters.GetNonce();
+#endif
initialAssociatedText = aeadParameters.GetAssociatedText();
int macSizeBits = aeadParameters.MacSize;
@@ -133,7 +141,11 @@ namespace Org.BouncyCastle.Crypto.Modes
}
else if (parameters is ParametersWithIV withIV)
{
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ newNonce = withIV.IV;
+#else
newNonce = withIV.GetIV();
+#endif
initialAssociatedText = null;
macSize = 16;
keyParam = (KeyParameter)withIV.Parameters;
@@ -146,12 +158,16 @@ namespace Org.BouncyCastle.Crypto.Modes
int bufLength = forEncryption ? BlockSize : (BlockSize + macSize);
this.bufBlock = new byte[bufLength];
- if (newNonce == null || newNonce.Length < 1)
+ if (newNonce.Length < 1)
throw new ArgumentException("IV must be at least 1 byte");
if (forEncryption)
{
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ if (nonce != null && newNonce.SequenceEqual(nonce))
+#else
if (nonce != null && Arrays.AreEqual(nonce, newNonce))
+#endif
{
if (keyParam == null)
throw new ArgumentException("cannot reuse nonce for GCM encryption");
@@ -161,7 +177,11 @@ namespace Org.BouncyCastle.Crypto.Modes
}
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ nonce = newNonce.ToArray();
+#else
nonce = newNonce;
+#endif
if (keyParam != null)
{
lastKey = keyParam.GetKey();
diff --git a/crypto/src/crypto/modes/GcmSivBlockCipher.cs b/crypto/src/crypto/modes/GcmSivBlockCipher.cs
index e11411433..d58fc0e65 100644
--- a/crypto/src/crypto/modes/GcmSivBlockCipher.cs
+++ b/crypto/src/crypto/modes/GcmSivBlockCipher.cs
@@ -176,21 +176,31 @@ namespace Org.BouncyCastle.Crypto.Modes
{
/* Set defaults */
byte[] myInitialAEAD = null;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ ReadOnlySpan<byte> myNonce;
+#else
byte[] myNonce;
+#endif
KeyParameter myKey;
/* Access parameters */
- if (cipherParameters is AeadParameters)
+ if (cipherParameters is AeadParameters myAEAD)
{
- AeadParameters myAEAD = (AeadParameters)cipherParameters;
myInitialAEAD = myAEAD.GetAssociatedText();
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ myNonce = myAEAD.Nonce;
+#else
myNonce = myAEAD.GetNonce();
+#endif
myKey = myAEAD.Key;
}
- else if (cipherParameters is ParametersWithIV)
+ else if (cipherParameters is ParametersWithIV myParms)
{
- ParametersWithIV myParms = (ParametersWithIV)cipherParameters;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ myNonce = myParms.IV;
+#else
myNonce = myParms.GetIV();
+#endif
myKey = (KeyParameter)myParms.Parameters;
}
else
@@ -199,28 +209,25 @@ namespace Org.BouncyCastle.Crypto.Modes
}
/* Check nonceSize */
- if (myNonce == null || myNonce.Length != NONCELEN)
- {
+ if (myNonce.Length != NONCELEN)
throw new ArgumentException("Invalid nonce");
- }
/* Check keysize */
if (myKey == null)
- {
throw new ArgumentException("Invalid key");
- }
- byte[] k = myKey.GetKey();
-
- if (k.Length != BUFLEN && k.Length != (BUFLEN << 1))
- {
+ int keyLength = myKey.KeyLength;
+ if (keyLength != BUFLEN && keyLength != (BUFLEN << 1))
throw new ArgumentException("Invalid key");
- }
/* Reset details */
forEncryption = pEncrypt;
theInitialAEAD = myInitialAEAD;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ theNonce = myNonce.ToArray();
+#else
theNonce = myNonce;
+#endif
/* Initialise the keys */
DeriveKeys(myKey);
diff --git a/crypto/src/crypto/modes/KCcmBlockCipher.cs b/crypto/src/crypto/modes/KCcmBlockCipher.cs
index c13c41543..6afb617b5 100644
--- a/crypto/src/crypto/modes/KCcmBlockCipher.cs
+++ b/crypto/src/crypto/modes/KCcmBlockCipher.cs
@@ -42,7 +42,7 @@ namespace Org.BouncyCastle.Crypto.Modes
*/
private int Nb_ = 4;
- private void setNb(int Nb)
+ private void SetNb(int Nb)
{
if (Nb == 4 || Nb == 6 || Nb == 8)
{
@@ -85,38 +85,32 @@ namespace Org.BouncyCastle.Crypto.Modes
this.buffer = new byte[engine.GetBlockSize()];
this.s = new byte[engine.GetBlockSize()];
this.counter = new byte[engine.GetBlockSize()];
- setNb(Nb);
+ SetNb(Nb);
}
public virtual void Init(bool forEncryption, ICipherParameters parameters)
{
-
- ICipherParameters cipherParameters;
- if (parameters is AeadParameters)
+ ICipherParameters cipherParameters;
+ if (parameters is AeadParameters param)
{
+ if (param.MacSize > MAX_MAC_BIT_LENGTH || param.MacSize < MIN_MAC_BIT_LENGTH || param.MacSize % 8 != 0)
+ throw new ArgumentException("Invalid mac size specified");
- AeadParameters param = (AeadParameters)parameters;
-
- if (param.MacSize > MAX_MAC_BIT_LENGTH || param.MacSize < MIN_MAC_BIT_LENGTH || param.MacSize % 8 != 0)
- {
- throw new ArgumentException("Invalid mac size specified");
- }
-
- nonce = param.GetNonce();
- macSize = param.MacSize / BITS_IN_BYTE;
- initialAssociatedText = param.GetAssociatedText();
- cipherParameters = param.Key;
+ nonce = param.GetNonce();
+ macSize = param.MacSize / BITS_IN_BYTE;
+ initialAssociatedText = param.GetAssociatedText();
+ cipherParameters = param.Key;
}
- else if (parameters is ParametersWithIV)
+ else if (parameters is ParametersWithIV paramsWithIV)
{
- nonce = ((ParametersWithIV)parameters).GetIV();
- macSize = engine.GetBlockSize(); // use default blockSize for MAC if it is not specified
- initialAssociatedText = null;
- cipherParameters = ((ParametersWithIV)parameters).Parameters;
+ nonce = paramsWithIV.GetIV();
+ macSize = engine.GetBlockSize(); // use default blockSize for MAC if it is not specified
+ initialAssociatedText = null;
+ cipherParameters = paramsWithIV.Parameters;
}
else
{
- throw new ArgumentException("Invalid parameters specified");
+ throw new ArgumentException("Invalid parameters specified");
}
this.mac = new byte[macSize];
@@ -133,10 +127,7 @@ namespace Org.BouncyCastle.Crypto.Modes
public virtual string AlgorithmName => engine.AlgorithmName + "/KCCM";
- public virtual int GetBlockSize()
- {
- return engine.GetBlockSize();
- }
+ public virtual int GetBlockSize() => engine.GetBlockSize();
public virtual IBlockCipher UnderlyingCipher => engine;
diff --git a/crypto/src/crypto/modes/OCBBlockCipher.cs b/crypto/src/crypto/modes/OCBBlockCipher.cs
index ce86780c5..c0bca2681 100644
--- a/crypto/src/crypto/modes/OCBBlockCipher.cs
+++ b/crypto/src/crypto/modes/OCBBlockCipher.cs
@@ -93,10 +93,18 @@ namespace Org.BouncyCastle.Crypto.Modes
KeyParameter keyParameter;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ ReadOnlySpan<byte> N;
+#else
byte[] N;
+#endif
if (parameters is AeadParameters aeadParameters)
{
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ N = aeadParameters.Nonce;
+#else
N = aeadParameters.GetNonce();
+#endif
initialAssociatedText = aeadParameters.GetAssociatedText();
int macSizeBits = aeadParameters.MacSize;
@@ -108,7 +116,11 @@ namespace Org.BouncyCastle.Crypto.Modes
}
else if (parameters is ParametersWithIV parametersWithIV)
{
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ N = parametersWithIV.IV;
+#else
N = parametersWithIV.GetIV();
+#endif
initialAssociatedText = null;
macSize = 16;
keyParameter = (KeyParameter) parametersWithIV.Parameters;
@@ -121,15 +133,8 @@ namespace Org.BouncyCastle.Crypto.Modes
this.hashBlock = new byte[16];
this.mainBlock = new byte[forEncryption ? BLOCK_SIZE : (BLOCK_SIZE + macSize)];
- if (N == null)
- {
- N = new byte[0];
- }
-
if (N.Length > 15)
- {
throw new ArgumentException("IV must be no more than 15 bytes");
- }
/*
* KEY-DEPENDENT INITIALISATION
@@ -221,6 +226,42 @@ namespace Org.BouncyCastle.Crypto.Modes
return bottom;
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ private int ProcessNonce(ReadOnlySpan<byte> N)
+ {
+ // TODO[api] Redesign to avoid this exceptional case
+ // Avoid problems if ProcessNonce() was overridden before this method even existed.
+ if (GetType() != typeof(OcbBlockCipher))
+ return ProcessNonce(N.ToArray());
+
+ Span<byte> nonce = stackalloc byte[16];
+ N.CopyTo(nonce[^N.Length..]);
+ nonce[0] = (byte)(macSize << 4);
+ nonce[15 - N.Length] |= 1;
+
+ int bottom = nonce[15] & 0x3F;
+ nonce[15] &= 0xC0;
+
+ /*
+ * When used with incrementing nonces, the cipher is only applied once every 64 inits.
+ */
+ if (KtopInput == null || !nonce.SequenceEqual(KtopInput))
+ {
+ KtopInput = nonce.ToArray();
+
+ Span<byte> Ktop = stackalloc byte[16];
+ hashCipher.ProcessBlock(KtopInput, Ktop);
+ Ktop.CopyTo(Stretch);
+ for (int i = 0; i < 8; ++i)
+ {
+ Stretch[16 + i] = (byte)(Ktop[i] ^ Ktop[i + 1]);
+ }
+ }
+
+ return bottom;
+ }
+#endif
+
public virtual int GetBlockSize()
{
return BLOCK_SIZE;
diff --git a/crypto/src/crypto/parameters/ParametersWithIV.cs b/crypto/src/crypto/parameters/ParametersWithIV.cs
index e642e828a..c5f04aab1 100644
--- a/crypto/src/crypto/parameters/ParametersWithIV.cs
+++ b/crypto/src/crypto/parameters/ParametersWithIV.cs
@@ -1,10 +1,28 @@
using System;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+using System.Buffers;
+#endif
namespace Org.BouncyCastle.Crypto.Parameters
{
public class ParametersWithIV
: ICipherParameters
{
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public static ParametersWithIV Create<TState>(ICipherParameters parameter, int ivLength, TState state,
+ SpanAction<byte, TState> action)
+ {
+ if (action == null)
+ throw new ArgumentNullException(nameof(action));
+ if (ivLength < 0)
+ throw new ArgumentOutOfRangeException(nameof(ivLength));
+
+ ParametersWithIV result = new ParametersWithIV(parameter, ivLength);
+ action(result.m_iv, state);
+ return result;
+ }
+#endif
+
internal static ICipherParameters ApplyOptionalIV(ICipherParameters parameters, byte[] iv)
{
return iv == null ? parameters : new ParametersWithIV(parameters, iv);
@@ -44,6 +62,16 @@ namespace Org.BouncyCastle.Crypto.Parameters
}
#endif
+ private ParametersWithIV(ICipherParameters parameters, int ivLength)
+ {
+ if (ivLength < 0)
+ throw new ArgumentOutOfRangeException(nameof(ivLength));
+
+ // NOTE: 'parameters' may be null to imply key re-use
+ m_parameters = parameters;
+ m_iv = new byte[ivLength];
+ }
+
public byte[] GetIV()
{
return (byte[])m_iv.Clone();
|