From d4c97933bee0ff57427c76bc99e5c6be46a1c65e Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 21 Oct 2022 16:11:20 +0700 Subject: Add Xor methods to Nat classes --- crypto/src/crypto/digests/HarakaBase.cs | 11 ++-- crypto/src/crypto/generators/SCrypt.cs | 15 ++--- crypto/src/math/raw/Nat.cs | 104 ++++++++++++++++++++++++++++++++ crypto/src/math/raw/Nat512.cs | 68 ++++++++++++++++++++- 4 files changed, 182 insertions(+), 16 deletions(-) diff --git a/crypto/src/crypto/digests/HarakaBase.cs b/crypto/src/crypto/digests/HarakaBase.cs index 37dda2163..1ca688914 100644 --- a/crypto/src/crypto/digests/HarakaBase.cs +++ b/crypto/src/crypto/digests/HarakaBase.cs @@ -102,7 +102,7 @@ namespace Org.BouncyCastle.Crypto.Digests s = SubBytes(s); s = ShiftRows(s); s = MixColumns(s); - XorWith(rk, s); + XorTo(rk, s); return s; } @@ -131,11 +131,14 @@ namespace Org.BouncyCastle.Crypto.Digests } #endif - private static void XorWith(byte[] x, byte[] z) + private static void XorTo(byte[] x, byte[] z) { - for (int i = 0; i < 16; ++i) + for (int i = 0; i < 16; i += 4) { - z[i] ^= x[i]; + z[i + 0] ^= x[i + 0]; + z[i + 1] ^= x[i + 1]; + z[i + 2] ^= x[i + 2]; + z[i + 3] ^= x[i + 3]; } } diff --git a/crypto/src/crypto/generators/SCrypt.cs b/crypto/src/crypto/generators/SCrypt.cs index 0c51d89bc..1a8d4a003 100644 --- a/crypto/src/crypto/generators/SCrypt.cs +++ b/crypto/src/crypto/generators/SCrypt.cs @@ -5,6 +5,7 @@ using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Utilities; +using Org.BouncyCastle.Math.Raw; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Generators @@ -143,8 +144,8 @@ namespace Org.BouncyCastle.Crypto.Generators int j = (int)(X[BCount - 16] & mask); uint[] V = VV[j >> chunkPow]; int VOff = (j & chunkMask) * BCount; - Array.Copy(V, VOff, blockY, 0, BCount); - Xor(blockY, X, 0, blockY); + Nat.Xor(BCount, V, VOff, X, 0, blockY, 0); + BlockMix(blockY, blockX1, blockX2, X, r); } @@ -165,7 +166,7 @@ namespace Org.BouncyCastle.Crypto.Generators for (int i = 2 * r; i > 0; --i) { - Xor(X1, B, BOff, X2); + Nat512.Xor(X1, 0, B, BOff, X2, 0); Salsa20Engine.SalsaCore(8, X2, X1); Array.Copy(X1, 0, Y, YOff, 16); @@ -175,14 +176,6 @@ namespace Org.BouncyCastle.Crypto.Generators } } - private static void Xor(uint[] a, uint[] b, int bOff, uint[] output) - { - for (int i = output.Length - 1; i >= 0; --i) - { - output[i] = a[i] ^ b[bOff + i]; - } - } - private static void Clear(Array array) { if (array != null) diff --git a/crypto/src/math/raw/Nat.cs b/crypto/src/math/raw/Nat.cs index 71c794197..89b6881d3 100644 --- a/crypto/src/math/raw/Nat.cs +++ b/crypto/src/math/raw/Nat.cs @@ -2640,6 +2640,110 @@ namespace Org.BouncyCastle.Math.Raw } #endif + public static void Xor(int len, uint[] x, uint[] y, uint[] z) + { + for (int i = 0; i < len; ++i) + { + z[i] = x[i] ^ y[i]; + } + } + + public static void Xor(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { + for (int i = 0; i < len; ++i) + { + z[zOff + i] = x[xOff + i] ^ y[yOff + i]; + } + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static void Xor(int len, ReadOnlySpan x, ReadOnlySpan y, Span z) + { + for (int i = 0; i < len; ++i) + { + z[i] = x[i] ^ y[i]; + } + } +#endif + + public static void Xor64(int len, ulong[] x, ulong[] y, ulong[] z) + { + for (int i = 0; i < len; ++i) + { + z[i] = x[i] ^ y[i]; + } + } + + public static void Xor64(int len, ulong[] x, int xOff, ulong[] y, int yOff, ulong[] z, int zOff) + { + for (int i = 0; i < len; ++i) + { + z[zOff + i] = x[xOff + i] ^ y[yOff + i]; + } + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static void Xor64(int len, ReadOnlySpan x, ReadOnlySpan y, Span z) + { + for (int i = 0; i < len; ++i) + { + z[i] = x[i] ^ y[i]; + } + } +#endif + + public static void XorTo(int len, uint[] x, uint[] z) + { + for (int i = 0; i < len; ++i) + { + z[i] ^= x[i]; + } + } + + public static void XorTo(int len, uint[] x, int xOff, uint[] z, int zOff) + { + for (int i = 0; i < len; ++i) + { + z[zOff + i] ^= x[xOff + i]; + } + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static void XorTo(int len, ReadOnlySpan x, Span z) + { + for (int i = 0; i < len; ++i) + { + z[i] ^= x[i]; + } + } +#endif + + public static void XorTo64(int len, ulong[] x, ulong[] z) + { + for (int i = 0; i < len; ++i) + { + z[i] ^= x[i]; + } + } + + public static void XorTo64(int len, ulong[] x, int xOff, ulong[] z, int zOff) + { + for (int i = 0; i < len; ++i) + { + z[zOff + i] ^= x[xOff + i]; + } + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static void XorTo64(int len, ReadOnlySpan x, Span z) + { + for (int i = 0; i < len; ++i) + { + z[i] ^= x[i]; + } + } +#endif + public static void Zero(int len, uint[] z) { #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER diff --git a/crypto/src/math/raw/Nat512.cs b/crypto/src/math/raw/Nat512.cs index a9ef2b3b6..6e8c593fd 100644 --- a/crypto/src/math/raw/Nat512.cs +++ b/crypto/src/math/raw/Nat512.cs @@ -1,5 +1,10 @@ using System; -using System.Diagnostics; +#if NETCOREAPP3_0_OR_GREATER +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +#endif namespace Org.BouncyCastle.Math.Raw { @@ -42,5 +47,66 @@ namespace Org.BouncyCastle.Math.Raw c24 += (uint)Nat.SubFrom(16, m, 0, zz, 8); Nat.AddWordAt(32, c24, zz, 24); } + + public static void Xor(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff) + { +#if NETCOREAPP3_0_OR_GREATER + if (Avx2.IsSupported && Unsafe.SizeOf>() == 32) + { + var X = MemoryMarshal.Cast(x.AsSpan(xOff, 16)); + var Y = MemoryMarshal.Cast(y.AsSpan(yOff, 16)); + var Z = MemoryMarshal.Cast(z.AsSpan(zOff, 16)); + + var X0 = MemoryMarshal.Read>(X[0x00..0x20]); + var X1 = MemoryMarshal.Read>(X[0x20..0x40]); + + var Y0 = MemoryMarshal.Read>(Y[0x00..0x20]); + var Y1 = MemoryMarshal.Read>(Y[0x20..0x40]); + + var Z0 = Avx2.Xor(X0, Y0); + var Z1 = Avx2.Xor(X1, Y1); + + MemoryMarshal.Write(Z[0x00..0x20], ref Z0); + MemoryMarshal.Write(Z[0x20..0x40], ref Z1); + return; + } + + if (Sse2.IsSupported && Unsafe.SizeOf>() == 16) + { + var X = MemoryMarshal.Cast(x.AsSpan(xOff, 16)); + var Y = MemoryMarshal.Cast(y.AsSpan(yOff, 16)); + var Z = MemoryMarshal.Cast(z.AsSpan(zOff, 16)); + + var X0 = MemoryMarshal.Read>(X[0x00..0x10]); + var X1 = MemoryMarshal.Read>(X[0x10..0x20]); + var X2 = MemoryMarshal.Read>(X[0x20..0x30]); + var X3 = MemoryMarshal.Read>(X[0x30..0x40]); + + var Y0 = MemoryMarshal.Read>(Y[0x00..0x10]); + var Y1 = MemoryMarshal.Read>(Y[0x10..0x20]); + var Y2 = MemoryMarshal.Read>(Y[0x20..0x30]); + var Y3 = MemoryMarshal.Read>(Y[0x30..0x40]); + + var Z0 = Sse2.Xor(X0, Y0); + var Z1 = Sse2.Xor(X1, Y1); + var Z2 = Sse2.Xor(X2, Y2); + var Z3 = Sse2.Xor(X3, Y3); + + MemoryMarshal.Write(Z[0x00..0x10], ref Z0); + MemoryMarshal.Write(Z[0x10..0x20], ref Z1); + MemoryMarshal.Write(Z[0x20..0x30], ref Z2); + MemoryMarshal.Write(Z[0x30..0x40], ref Z3); + return; + } +#endif + + for (int i = 0; i < 16; i += 4) + { + z[zOff + i + 0] = x[xOff + i + 0] ^ y[yOff + i + 0]; + z[zOff + i + 1] = x[xOff + i + 1] ^ y[yOff + i + 1]; + z[zOff + i + 2] = x[xOff + i + 2] ^ y[yOff + i + 2]; + z[zOff + i + 3] = x[xOff + i + 3] ^ y[yOff + i + 3]; + } + } } } -- cgit 1.4.1