diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2023-02-15 13:15:00 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2023-02-15 13:15:00 +0700 |
commit | 4c9ad931bf856090f92ab2d3239052f3a1445896 (patch) | |
tree | f152cebdfee0a26efbd99399edff5b0912dfbb57 | |
parent | Refactor AsconEngine (diff) | |
download | BouncyCastle.NET-ed25519-4c9ad931bf856090f92ab2d3239052f3a1445896.tar.xz |
Refactor AsconEngine AAD phase
-rw-r--r-- | crypto/src/crypto/engines/AsconEngine.cs | 206 |
1 files changed, 122 insertions, 84 deletions
diff --git a/crypto/src/crypto/engines/AsconEngine.cs b/crypto/src/crypto/engines/AsconEngine.cs index a5eec3f3a..43b5eff15 100644 --- a/crypto/src/crypto/engines/AsconEngine.cs +++ b/crypto/src/crypto/engines/AsconEngine.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.IO; #if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER using System.Runtime.CompilerServices; @@ -39,7 +40,6 @@ namespace Org.BouncyCastle.Crypto.Engines DecFinal = 8, } - private readonly MemoryStream aadData = new MemoryStream(); private readonly MemoryStream message = new MemoryStream(); private readonly AsconParameters asconParameters; @@ -62,6 +62,9 @@ namespace Org.BouncyCastle.Crypto.Engines private string algorithmName; private State m_state = State.Uninitialized; + private readonly byte[] m_buf; + private int m_bufPos = 0; + public AsconEngine(AsconParameters asconParameters) { this.asconParameters = asconParameters; @@ -92,6 +95,8 @@ namespace Org.BouncyCastle.Crypto.Engines throw new ArgumentException("invalid parameter setting for ASCON AEAD"); } nr = (ASCON_AEAD_RATE == 8) ? 6 : 8; + + m_buf = new byte[ASCON_AEAD_RATE]; } public int GetKeyBytesSize() @@ -149,24 +154,95 @@ namespace Org.BouncyCastle.Crypto.Engines { CheckAad(); - aadData.WriteByte(input); + m_buf[m_bufPos] = input; + if (++m_bufPos == ASCON_AEAD_RATE) + { +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + ProcessBufferAad(m_buf); +#else + ProcessBufferAad(m_buf, 0); +#endif + m_bufPos = 0; + } } public void ProcessAadBytes(byte[] inBytes, int inOff, int len) { Check.DataLength(inBytes, inOff, len, "input buffer too short"); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + ProcessAadBytes(inBytes.AsSpan(inOff, len)); +#else + // Don't enter AAD state until we actually get input + if (len <= 0) + return; + CheckAad(); - aadData.Write(inBytes, inOff, len); + if (m_bufPos > 0) + { + int available = ASCON_AEAD_RATE - m_bufPos; + if (len < available) + { + Array.Copy(inBytes, inOff, m_buf, m_bufPos, len); + m_bufPos += len; + return; + } + + Array.Copy(inBytes, inOff, m_buf, m_bufPos, available); + inOff += available; + len -= available; + + ProcessBufferAad(m_buf, 0); + //m_bufPos = 0; + } + + while (len >= ASCON_AEAD_RATE) + { + ProcessBufferAad(inBytes, inOff); + inOff += ASCON_AEAD_RATE; + len -= ASCON_AEAD_RATE; + } + + Array.Copy(inBytes, inOff, m_buf, m_bufPos, len); + m_bufPos = len; +#endif } #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER public void ProcessAadBytes(ReadOnlySpan<byte> input) { + // Don't enter AAD state until we actually get input + if (input.IsEmpty) + return; + CheckAad(); - aadData.Write(input); + if (m_bufPos > 0) + { + int available = ASCON_AEAD_RATE - m_bufPos; + if (input.Length < available) + { + input.CopyTo(m_buf.AsSpan(m_bufPos)); + m_bufPos += input.Length; + return; + } + + input[..available].CopyTo(m_buf.AsSpan(m_bufPos)); + input = input[available..]; + + ProcessBufferAad(m_buf); + //m_bufPos = 0; + } + + while (input.Length >= ASCON_AEAD_RATE) + { + ProcessBufferAad(input); + input = input[ASCON_AEAD_RATE..]; + } + + input.CopyTo(m_buf); + m_bufPos = input.Length; } #endif @@ -387,15 +463,33 @@ namespace Org.BouncyCastle.Crypto.Engines private void FinishAad(State nextState) { - byte[] aad = aadData.GetBuffer(); - int aadLen = Convert.ToInt32(aadData.Length); + // State indicates whether we ever received AAD + switch (m_state) + { + case State.DecAad: + case State.EncAad: + { + m_buf[m_bufPos] = 0x80; -#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - ascon_adata(aad.AsSpan(0, aadLen)); -#else - ascon_adata(aad, 0, aadLen); -#endif + if (m_bufPos >= 8) // ASCON_AEAD_RATE == 16 is implied + { + x0 ^= Pack.BE_To_UInt64(m_buf, 0); + x1 ^= Pack.BE_To_UInt64(m_buf, 8) & (ulong.MaxValue << (56 - ((m_bufPos - 8) << 3))); + } + else + { + x0 ^= Pack.BE_To_UInt64(m_buf, 0) & (ulong.MaxValue << (56 - (m_bufPos << 3))); + } + P(nr); + break; + } + } + + // domain separation + x4 ^= 1UL; + + m_bufPos = 0; m_state = nextState; } @@ -495,44 +589,16 @@ namespace Org.BouncyCastle.Crypto.Engines return outLen; } - private void ascon_adata(ReadOnlySpan<byte> aad) + private void ProcessBufferAad(ReadOnlySpan<byte> aad) { - if (!aad.IsEmpty) + Debug.Assert(aad.Length >= ASCON_AEAD_RATE); + + x0 ^= Pack.BE_To_UInt64(aad); + if (ASCON_AEAD_RATE == 16) { - /* full associated data blocks */ - while (aad.Length >= ASCON_AEAD_RATE) - { - x0 ^= Pack.BE_To_UInt64(aad); - if (ASCON_AEAD_RATE == 16) - { - x1 ^= Pack.BE_To_UInt64(aad[8..]); - } - P(nr); - aad = aad[ASCON_AEAD_RATE..]; - } - /* final associated data block */ - if (ASCON_AEAD_RATE == 16 && aad.Length >= 8) - { - x0 ^= Pack.BE_To_UInt64(aad); - aad = aad[8..]; - x1 ^= PAD(aad.Length); - if (!aad.IsEmpty) - { - x1 ^= Pack.BE_To_UInt64_High(aad); - } - } - else - { - x0 ^= PAD(aad.Length); - if (!aad.IsEmpty) - { - x0 ^= Pack.BE_To_UInt64_High(aad); - } - } - P(nr); + x1 ^= Pack.BE_To_UInt64(aad[8..]); } - /* domain separation */ - x4 ^= 1UL; + P(nr); } private void ascon_encrypt(Span<byte> c, ReadOnlySpan<byte> m) @@ -690,46 +756,16 @@ namespace Org.BouncyCastle.Crypto.Engines return outLen; } - private void ascon_adata(byte[] aad, int aadOff, int aadLen) + private void ProcessBufferAad(byte[] aad, int aadOff) { - if (aadLen != 0) + Debug.Assert(aad.Length - ASCON_AEAD_RATE >= aadOff); + + x0 ^= Pack.BE_To_UInt64(aad, aadOff); + if (ASCON_AEAD_RATE == 16) { - /* full associated data blocks */ - while (aadLen >= ASCON_AEAD_RATE) - { - x0 ^= Pack.BE_To_UInt64(aad, aadOff); - if (ASCON_AEAD_RATE == 16) - { - x1 ^= Pack.BE_To_UInt64(aad, aadOff + 8); - } - P(nr); - aadOff += ASCON_AEAD_RATE; - aadLen -= ASCON_AEAD_RATE; - } - /* final associated data block */ - if (ASCON_AEAD_RATE == 16 && aadLen >= 8) - { - x0 ^= Pack.BE_To_UInt64(aad, aadOff); - aadOff += 8; - aadLen -= 8; - x1 ^= PAD(aadLen); - if (aadLen != 0) - { - x1 ^= Pack.BE_To_UInt64_High(aad, aadOff, aadLen); - } - } - else - { - x0 ^= PAD(aadLen); - if (aadLen != 0) - { - x0 ^= Pack.BE_To_UInt64_High(aad, aadOff, aadLen); - } - } - P(nr); + x1 ^= Pack.BE_To_UInt64(aad, aadOff + 8); } - /* domain separation */ - x4 ^= 1UL; + P(nr); } private void ascon_encrypt(byte[] c, int cOff, byte[] m, int mOff, int mlen) @@ -868,9 +904,11 @@ namespace Org.BouncyCastle.Crypto.Engines mac = null; } - aadData.SetLength(0); message.SetLength(0); + Arrays.Clear(m_buf); + m_bufPos = 0; + switch (m_state) { case State.DecInit: |