From 42237911149b2e339e454fb149d5ac7301614a27 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Wed, 12 Oct 2022 12:03:29 +0700 Subject: Improve digest API compliance in sphincs haraka impls --- .../src/pqc/crypto/sphincsplus/HarakaS256Digest.cs | 30 ++++++++++++++++++-- .../src/pqc/crypto/sphincsplus/HarakaS512Digest.cs | 32 ++++++++++++++++++++-- crypto/src/pqc/crypto/sphincsplus/HarakaSBase.cs | 27 ++++++++++++++++-- 3 files changed, 83 insertions(+), 6 deletions(-) (limited to 'crypto/src') diff --git a/crypto/src/pqc/crypto/sphincsplus/HarakaS256Digest.cs b/crypto/src/pqc/crypto/sphincsplus/HarakaS256Digest.cs index 2e22bfea1..90a5a0dbb 100644 --- a/crypto/src/pqc/crypto/sphincsplus/HarakaS256Digest.cs +++ b/crypto/src/pqc/crypto/sphincsplus/HarakaS256Digest.cs @@ -17,7 +17,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus return 32; } - public void BlockUpdate(byte input) + public void Update(byte input) { if (off > 32 - 1) throw new ArgumentException("total input cannot be more than 32 bytes"); @@ -34,6 +34,17 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus off += len; } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public void BlockUpdate(ReadOnlySpan input) + { + if (off > 32 - input.Length) + throw new ArgumentException("total input cannot be more than 32 bytes"); + + input.CopyTo(buffer.AsSpan(off)); + off += input.Length; + } +#endif + public int DoFinal(byte[] output, int outOff) { // TODO Check received all 32 bytes of input? @@ -44,7 +55,22 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus Reset(); - return output.Length; + return 32; + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public int DoFinal(Span output) + { + // TODO Check received all 32 bytes of input? + + Span s = stackalloc byte[32]; + Haraka256Perm(s); + Xor(s, buffer, output[..32]); + + Reset(); + + return 32; } +#endif } } diff --git a/crypto/src/pqc/crypto/sphincsplus/HarakaS512Digest.cs b/crypto/src/pqc/crypto/sphincsplus/HarakaS512Digest.cs index c83eb8d8c..d96509f62 100644 --- a/crypto/src/pqc/crypto/sphincsplus/HarakaS512Digest.cs +++ b/crypto/src/pqc/crypto/sphincsplus/HarakaS512Digest.cs @@ -40,6 +40,17 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus off += len; } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public void BlockUpdate(ReadOnlySpan input) + { + if (off > 64 - input.Length) + throw new ArgumentException("total input cannot be more than 64 bytes"); + + input.CopyTo(buffer.AsSpan(off)); + off += input.Length; + } +#endif + public int DoFinal(byte[] output, int outOff) { // TODO Check received all 64 bytes of input? @@ -52,7 +63,24 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus Reset(); - return s.Length; + return 32; + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public int DoFinal(Span output) + { + // TODO Check received all 64 bytes of input? + + Span s = stackalloc byte[64]; + Haraka512Perm(s); + Xor(s[8..], buffer.AsSpan(8), output[..8]); + Xor(s[24..], buffer.AsSpan(24), output[8..24]); + Xor(s[48..], buffer.AsSpan(48), output[24..32]); + + Reset(); + + return 32; } +#endif } -} \ No newline at end of file +} diff --git a/crypto/src/pqc/crypto/sphincsplus/HarakaSBase.cs b/crypto/src/pqc/crypto/sphincsplus/HarakaSBase.cs index fa96512ea..5efafc1db 100644 --- a/crypto/src/pqc/crypto/sphincsplus/HarakaSBase.cs +++ b/crypto/src/pqc/crypto/sphincsplus/HarakaSBase.cs @@ -65,7 +65,11 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus BrAesCtOrtho(output); } - protected void Haraka512Perm(byte[] output) +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + internal void Haraka512Perm(Span output) +#else + internal void Haraka512Perm(byte[] output) +#endif { uint[] w = new uint[16]; ulong[] q = new ulong[8]; @@ -116,7 +120,11 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus } } - protected void Haraka256Perm(byte[] output) +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + internal void Haraka256Perm(Span output) +#else + internal void Haraka256Perm(byte[] output) +#endif { uint[] q = new uint[8]; InterleaveConstant32(q, buffer, 0); @@ -138,8 +146,13 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus BrAesCtOrtho(q); for (int i = 0; i < 4; i++) { +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Pack.UInt32_To_LE(q[i << 1], output[(i << 2)..]); + Pack.UInt32_To_LE(q[(i << 1) + 1], output[((i << 2) + 16)..]); +#else Pack.UInt32_To_LE(q[i << 1], output, i << 2); Pack.UInt32_To_LE(q[(i << 1) + 1], output, (i << 2) + 16); +#endif } } @@ -678,5 +691,15 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus z[zOff + i] = (byte)(x[xOff + i] ^ y[yOff + i]); } } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + protected static void Xor(ReadOnlySpan x, ReadOnlySpan y, Span z) + { + for (int i = 0; i < z.Length; i++) + { + z[i] = (byte)(x[i] ^ y[i]); + } + } +#endif } } -- cgit 1.4.1