diff options
author | David Hook <dgh@cryptoworkshop.com> | 2022-08-08 17:38:07 +1000 |
---|---|---|
committer | David Hook <dgh@cryptoworkshop.com> | 2022-08-08 17:38:07 +1000 |
commit | f8defaf942ebd8424243794230b5452636d02ca4 (patch) | |
tree | b1209d6e0be6720dbb98957c787f918cee6d85ab | |
parent | Initial Falcon implementation (diff) | |
parent | Remove unnecessary AsSpan (diff) | |
download | BouncyCastle.NET-ed25519-f8defaf942ebd8424243794230b5452636d02ca4.tar.xz |
Merge remote-tracking branch 'refs/remotes/origin/master'
29 files changed, 486 insertions, 295 deletions
diff --git a/crypto/src/crmf/PKMacBuilder.cs b/crypto/src/crmf/PKMacBuilder.cs index 156936eac..9b483fbfb 100644 --- a/crypto/src/crmf/PKMacBuilder.cs +++ b/crypto/src/crmf/PKMacBuilder.cs @@ -83,6 +83,15 @@ namespace Org.BouncyCastle.Crmf signature.CopyTo(sig, sigOff); return signature.Length; } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public int Collect(Span<byte> destination) + { + byte[] result = Collect(); + result.CopyTo(destination); + return result.Length; + } +#endif } public class PKMacBuilder diff --git a/crypto/src/crypto/Check.cs b/crypto/src/crypto/Check.cs index 81d07e23c..36263dc24 100644 --- a/crypto/src/crypto/Check.cs +++ b/crypto/src/crypto/Check.cs @@ -23,7 +23,7 @@ namespace Org.BouncyCastle.Crypto } #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - internal static void DataLength(Span<byte> input, int len, string msg) + internal static void DataLength(ReadOnlySpan<byte> input, int len, string msg) { if (input.Length < len) throw new DataLengthException(msg); diff --git a/crypto/src/crypto/IBlockResult.cs b/crypto/src/crypto/IBlockResult.cs index 0f054fedc..3ed96a7c1 100644 --- a/crypto/src/crypto/IBlockResult.cs +++ b/crypto/src/crypto/IBlockResult.cs @@ -1,4 +1,5 @@ - +using System; + namespace Org.BouncyCastle.Crypto { /// <summary> @@ -20,5 +21,14 @@ namespace Org.BouncyCastle.Crypto /// <param name="destination">The byte array to copy the result into.</param> /// <param name="offset">The offset into destination to start copying the result at.</param> int Collect(byte[] destination, int offset); + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + /// <summary> + /// Store the final result of the operation by copying it into the destination span. + /// </summary> + /// <returns>The number of bytes copied into destination.</returns> + /// <param name="destination">The span to copy the result into.</param> + int Collect(Span<byte> destination); +#endif } } diff --git a/crypto/src/crypto/SimpleBlockResult.cs b/crypto/src/crypto/SimpleBlockResult.cs index 6cacda63f..35432c2b3 100644 --- a/crypto/src/crypto/SimpleBlockResult.cs +++ b/crypto/src/crypto/SimpleBlockResult.cs @@ -49,5 +49,14 @@ namespace Org.BouncyCastle.Crypto return result.Length; } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public int Collect(Span<byte> destination) + { + result.CopyTo(destination); + + return result.Length; + } +#endif } } diff --git a/crypto/src/crypto/digests/RipeMD128Digest.cs b/crypto/src/crypto/digests/RipeMD128Digest.cs index e8a0331ca..cba2c65d3 100644 --- a/crypto/src/crypto/digests/RipeMD128Digest.cs +++ b/crypto/src/crypto/digests/RipeMD128Digest.cs @@ -1,5 +1,6 @@ using System; +using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Digests @@ -57,12 +58,9 @@ namespace Org.BouncyCastle.Crypto.Digests return DigestLength; } - internal override void ProcessWord( - byte[] input, - int inOff) + internal override void ProcessWord(byte[] input, int inOff) { - X[xOff++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8) - | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24); + X[xOff++] = (int)Pack.LE_To_UInt32(input, inOff); if (xOff == 16) { @@ -82,27 +80,14 @@ namespace Org.BouncyCastle.Crypto.Digests X[15] = (int)((ulong) bitLength >> 32); } - private void UnpackWord( - int word, - byte[] outBytes, - int outOff) - { - outBytes[outOff] = (byte)word; - outBytes[outOff + 1] = (byte)((uint) word >> 8); - outBytes[outOff + 2] = (byte)((uint) word >> 16); - outBytes[outOff + 3] = (byte)((uint) word >> 24); - } - - public override int DoFinal( - byte[] output, - int outOff) + public override int DoFinal(byte[] output, int outOff) { Finish(); - UnpackWord(H0, output, outOff); - UnpackWord(H1, output, outOff + 4); - UnpackWord(H2, output, outOff + 8); - UnpackWord(H3, output, outOff + 12); + Pack.UInt32_To_LE((uint)H0, output, outOff); + Pack.UInt32_To_LE((uint)H1, output, outOff + 4); + Pack.UInt32_To_LE((uint)H2, output, outOff + 8); + Pack.UInt32_To_LE((uint)H3, output, outOff + 12); Reset(); @@ -478,7 +463,5 @@ namespace Org.BouncyCastle.Crypto.Digests CopyIn(d); } - } - } diff --git a/crypto/src/crypto/digests/RipeMD160Digest.cs b/crypto/src/crypto/digests/RipeMD160Digest.cs index af4aa44bb..0fc2a4a1c 100644 --- a/crypto/src/crypto/digests/RipeMD160Digest.cs +++ b/crypto/src/crypto/digests/RipeMD160Digest.cs @@ -1,5 +1,6 @@ using System; +using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Digests @@ -59,12 +60,9 @@ namespace Org.BouncyCastle.Crypto.Digests return DigestLength; } - internal override void ProcessWord( - byte[] input, - int inOff) + internal override void ProcessWord(byte[] input, int inOff) { - X[xOff++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8) - | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24); + X[xOff++] = (int)Pack.LE_To_UInt32(input, inOff); if (xOff == 16) { @@ -72,7 +70,7 @@ namespace Org.BouncyCastle.Crypto.Digests } } - internal override void ProcessLength( + internal override void ProcessLength( long bitLength) { if (xOff > 14) @@ -84,28 +82,15 @@ namespace Org.BouncyCastle.Crypto.Digests X[15] = (int)((ulong) bitLength >> 32); } - private void UnpackWord( - int word, - byte[] outBytes, - int outOff) - { - outBytes[outOff] = (byte)word; - outBytes[outOff + 1] = (byte)((uint) word >> 8); - outBytes[outOff + 2] = (byte)((uint) word >> 16); - outBytes[outOff + 3] = (byte)((uint) word >> 24); - } - - public override int DoFinal( - byte[] output, - int outOff) + public override int DoFinal(byte[] output, int outOff) { Finish(); - UnpackWord(H0, output, outOff); - UnpackWord(H1, output, outOff + 4); - UnpackWord(H2, output, outOff + 8); - UnpackWord(H3, output, outOff + 12); - UnpackWord(H4, output, outOff + 16); + Pack.UInt32_To_LE((uint)H0, output, outOff); + Pack.UInt32_To_LE((uint)H1, output, outOff + 4); + Pack.UInt32_To_LE((uint)H2, output, outOff + 8); + Pack.UInt32_To_LE((uint)H3, output, outOff + 12); + Pack.UInt32_To_LE((uint)H4, output, outOff + 16); Reset(); @@ -439,7 +424,5 @@ namespace Org.BouncyCastle.Crypto.Digests CopyIn(d); } - } - } diff --git a/crypto/src/crypto/digests/RipeMD256Digest.cs b/crypto/src/crypto/digests/RipeMD256Digest.cs index 306275767..621162a6f 100644 --- a/crypto/src/crypto/digests/RipeMD256Digest.cs +++ b/crypto/src/crypto/digests/RipeMD256Digest.cs @@ -1,5 +1,6 @@ using System; +using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Digests @@ -59,12 +60,9 @@ namespace Org.BouncyCastle.Crypto.Digests xOff = t.xOff; } - internal override void ProcessWord( - byte[] input, - int inOff) + internal override void ProcessWord(byte[] input, int inOff) { - X[xOff++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8) - | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24); + X[xOff++] = (int)Pack.LE_To_UInt32(input, inOff); if (xOff == 16) { @@ -84,29 +82,18 @@ namespace Org.BouncyCastle.Crypto.Digests X[15] = (int)((ulong)bitLength >> 32); } - private void UnpackWord( - int word, - byte[] outBytes, - int outOff) - { - outBytes[outOff] = (byte)(uint)word; - outBytes[outOff + 1] = (byte)((uint)word >> 8); - outBytes[outOff + 2] = (byte)((uint)word >> 16); - outBytes[outOff + 3] = (byte)((uint)word >> 24); - } - public override int DoFinal(byte[] output, int outOff) { Finish(); - UnpackWord(H0, output, outOff); - UnpackWord(H1, output, outOff + 4); - UnpackWord(H2, output, outOff + 8); - UnpackWord(H3, output, outOff + 12); - UnpackWord(H4, output, outOff + 16); - UnpackWord(H5, output, outOff + 20); - UnpackWord(H6, output, outOff + 24); - UnpackWord(H7, output, outOff + 28); + Pack.UInt32_To_LE((uint)H0, output, outOff); + Pack.UInt32_To_LE((uint)H1, output, outOff + 4); + Pack.UInt32_To_LE((uint)H2, output, outOff + 8); + Pack.UInt32_To_LE((uint)H3, output, outOff + 12); + Pack.UInt32_To_LE((uint)H4, output, outOff + 16); + Pack.UInt32_To_LE((uint)H5, output, outOff + 20); + Pack.UInt32_To_LE((uint)H6, output, outOff + 24); + Pack.UInt32_To_LE((uint)H7, output, outOff + 28); Reset(); @@ -425,6 +412,5 @@ namespace Org.BouncyCastle.Crypto.Digests CopyIn(d); } - } } diff --git a/crypto/src/crypto/digests/RipeMD320Digest.cs b/crypto/src/crypto/digests/RipeMD320Digest.cs index 767d74dba..c46bc4fea 100644 --- a/crypto/src/crypto/digests/RipeMD320Digest.cs +++ b/crypto/src/crypto/digests/RipeMD320Digest.cs @@ -1,5 +1,6 @@ using System; +using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Digests @@ -62,12 +63,9 @@ namespace Org.BouncyCastle.Crypto.Digests xOff = t.xOff; } - internal override void ProcessWord( - byte[] input, - int inOff) + internal override void ProcessWord(byte[] input, int inOff) { - X[xOff++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8) - | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24); + X[xOff++] = (int)Pack.LE_To_UInt32(input, inOff); if (xOff == 16) { @@ -87,31 +85,20 @@ namespace Org.BouncyCastle.Crypto.Digests X[15] = (int)((ulong)bitLength >> 32); } - private void UnpackWord( - int word, - byte[] outBytes, - int outOff) - { - outBytes[outOff] = (byte)word; - outBytes[outOff + 1] = (byte)((uint)word >> 8); - outBytes[outOff + 2] = (byte)((uint)word >> 16); - outBytes[outOff + 3] = (byte)((uint)word >> 24); - } - public override int DoFinal(byte[] output, int outOff) { Finish(); - UnpackWord(H0, output, outOff); - UnpackWord(H1, output, outOff + 4); - UnpackWord(H2, output, outOff + 8); - UnpackWord(H3, output, outOff + 12); - UnpackWord(H4, output, outOff + 16); - UnpackWord(H5, output, outOff + 20); - UnpackWord(H6, output, outOff + 24); - UnpackWord(H7, output, outOff + 28); - UnpackWord(H8, output, outOff + 32); - UnpackWord(H9, output, outOff + 36); + Pack.UInt32_To_LE((uint)H0, output, outOff); + Pack.UInt32_To_LE((uint)H1, output, outOff + 4); + Pack.UInt32_To_LE((uint)H2, output, outOff + 8); + Pack.UInt32_To_LE((uint)H3, output, outOff + 12); + Pack.UInt32_To_LE((uint)H4, output, outOff + 16); + Pack.UInt32_To_LE((uint)H5, output, outOff + 20); + Pack.UInt32_To_LE((uint)H6, output, outOff + 24); + Pack.UInt32_To_LE((uint)H7, output, outOff + 28); + Pack.UInt32_To_LE((uint)H8, output, outOff + 32); + Pack.UInt32_To_LE((uint)H9, output, outOff + 36); Reset(); @@ -454,6 +441,5 @@ namespace Org.BouncyCastle.Crypto.Digests CopyIn(d); } - } } diff --git a/crypto/src/crypto/digests/SkeinEngine.cs b/crypto/src/crypto/digests/SkeinEngine.cs index 2f38115d2..a36ac8fe7 100644 --- a/crypto/src/crypto/digests/SkeinEngine.cs +++ b/crypto/src/crypto/digests/SkeinEngine.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.Collections; @@ -75,7 +76,7 @@ namespace Org.BouncyCastle.Crypto.Digests bytes[5] = 0; // 8..15 = output length - ThreefishEngine.WordToBytes((ulong)outputSizeBits, bytes, 8); + Pack.UInt64_To_LE((ulong)outputSizeBits, bytes, 8); } public byte[] Bytes @@ -441,10 +442,7 @@ namespace Org.BouncyCastle.Crypto.Digests private void ProcessBlock(ulong[] output) { engine.threefish.Init(true, engine.chain, tweak.GetWords()); - for (int i = 0; i < message.Length; i++) - { - message[i] = ThreefishEngine.BytesToWord(currentBlock, i * 8); - } + Pack.LE_To_UInt64(currentBlock, 0, message); engine.threefish.ProcessBlock(message, output); @@ -465,7 +463,6 @@ namespace Org.BouncyCastle.Crypto.Digests tweak.Final = true; ProcessBlock(output); } - } /** @@ -776,31 +773,28 @@ namespace Org.BouncyCastle.Crypto.Digests private void Output(ulong outputSequence, byte[] outBytes, int outOff, int outputBytes) { byte[] currentBytes = new byte[8]; - ThreefishEngine.WordToBytes(outputSequence, currentBytes, 0); + Pack.UInt64_To_LE(outputSequence, currentBytes, 0); - // Output is a sequence of UBI invocations all of which use and preserve the pre-output - // state + // Output is a sequence of UBI invocations all of which use and preserve the pre-output state ulong[] outputWords = new ulong[chain.Length]; UbiInit(PARAM_TYPE_OUTPUT); this.ubi.Update(currentBytes, 0, currentBytes.Length, outputWords); ubi.DoFinal(outputWords); - int wordsRequired = ((outputBytes + 8 - 1) / 8); + int wordsRequired = (outputBytes + 8 - 1) / 8; for (int i = 0; i < wordsRequired; i++) { int toWrite = System.Math.Min(8, outputBytes - (i * 8)); if (toWrite == 8) { - ThreefishEngine.WordToBytes(outputWords[i], outBytes, outOff + (i * 8)); + Pack.UInt64_To_LE(outputWords[i], outBytes, outOff + (i * 8)); } else { - ThreefishEngine.WordToBytes(outputWords[i], currentBytes, 0); + Pack.UInt64_To_LE(outputWords[i], currentBytes, 0); Array.Copy(currentBytes, 0, outBytes, outOff + (i * 8), toWrite); } } } - } } - diff --git a/crypto/src/crypto/digests/TigerDigest.cs b/crypto/src/crypto/digests/TigerDigest.cs index ce9efdbed..a452d3f0b 100644 --- a/crypto/src/crypto/digests/TigerDigest.cs +++ b/crypto/src/crypto/digests/TigerDigest.cs @@ -1,6 +1,6 @@ using System; -using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Digests @@ -553,7 +553,7 @@ namespace Org.BouncyCastle.Crypto.Digests // // buffers // - private byte[] Buffer = new byte[8]; + private byte[] m_buffer = new byte[8]; private int bOff; private long[] x = new long[8]; @@ -591,18 +591,9 @@ namespace Org.BouncyCastle.Crypto.Digests return MyByteLength; } - private void ProcessWord( - byte[] b, - int off) + private void ProcessWord(byte[] b, int off) { - x[xOff++] = ((long)(b[off + 7] & 0xff) << 56) - | ((long)(b[off + 6] & 0xff) << 48) - | ((long)(b[off + 5] & 0xff) << 40) - | ((long)(b[off + 4] & 0xff) << 32) - | ((long)(b[off + 3] & 0xff) << 24) - | ((long)(b[off + 2] & 0xff) << 16) - | ((long)(b[off + 1] & 0xff) << 8) - | ((uint)(b[off + 0] & 0xff)); + x[xOff++] = (long)Pack.LE_To_UInt64(b, off); if (xOff == x.Length) { @@ -615,11 +606,11 @@ namespace Org.BouncyCastle.Crypto.Digests public void Update( byte input) { - Buffer[bOff++] = input; + m_buffer[bOff++] = input; - if (bOff == Buffer.Length) + if (bOff == m_buffer.Length) { - ProcessWord(Buffer, 0); + ProcessWord(m_buffer, 0); } byteCount++; @@ -781,21 +772,6 @@ namespace Org.BouncyCastle.Crypto.Digests } } - private void UnpackWord( - long r, - byte[] output, - int outOff) - { - output[outOff + 7] = (byte)(r >> 56); - output[outOff + 6] = (byte)(r >> 48); - output[outOff + 5] = (byte)(r >> 40); - output[outOff + 4] = (byte)(r >> 32); - output[outOff + 3] = (byte)(r >> 24); - output[outOff + 2] = (byte)(r >> 16); - output[outOff + 1] = (byte)(r >> 8); - output[outOff] = (byte)r; - } - private void ProcessLength( long bitLength) { @@ -824,9 +800,9 @@ namespace Org.BouncyCastle.Crypto.Digests { Finish(); - UnpackWord(a, output, outOff); - UnpackWord(b, output, outOff + 8); - UnpackWord(c, output, outOff + 16); + Pack.UInt64_To_LE((ulong)a, output, outOff); + Pack.UInt64_To_LE((ulong)b, output, outOff + 8); + Pack.UInt64_To_LE((ulong)c, output, outOff + 16); Reset(); @@ -849,9 +825,9 @@ namespace Org.BouncyCastle.Crypto.Digests } bOff = 0; - for (int i = 0; i != Buffer.Length; i++) + for (int i = 0; i != m_buffer.Length; i++) { - Buffer[i] = 0; + m_buffer[i] = 0; } byteCount = 0; @@ -873,11 +849,10 @@ namespace Org.BouncyCastle.Crypto.Digests Array.Copy(t.x, 0, x, 0, t.x.Length); xOff = t.xOff; - Array.Copy(t.Buffer, 0, Buffer, 0, t.Buffer.Length); + Array.Copy(t.m_buffer, 0, m_buffer, 0, t.m_buffer.Length); bOff = t.bOff; byteCount = t.byteCount; } - } } diff --git a/crypto/src/crypto/engines/AesX86Engine.cs b/crypto/src/crypto/engines/AesX86Engine.cs index a7dcfc686..a270c2ad2 100644 --- a/crypto/src/crypto/engines/AesX86Engine.cs +++ b/crypto/src/crypto/engines/AesX86Engine.cs @@ -190,7 +190,7 @@ namespace Org.BouncyCastle.Crypto.Engines return 16; } - public int ProcessBlock(Span<byte> input, Span<byte> output) + public int ProcessBlock(ReadOnlySpan<byte> input, Span<byte> output) { Check.DataLength(input, 16, "input buffer too short"); Check.OutputLength(output, 16, "output buffer too short"); @@ -329,13 +329,13 @@ namespace Org.BouncyCastle.Crypto.Engines } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector128<byte> Load128(Span<byte> t) + private static Vector128<byte> Load128(ReadOnlySpan<byte> t) { #if NET7_0_OR_GREATER return Vector128.Create<byte>(t); #else if (BitConverter.IsLittleEndian && Unsafe.SizeOf<Vector128<byte>>() == 16) - return Unsafe.ReadUnaligned<Vector128<byte>>(ref t[0]); + return Unsafe.ReadUnaligned<Vector128<byte>>(ref Unsafe.AsRef(t[0])); return Vector128.Create(t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8], t[9], t[10], t[11], t[12], t[13], t[14], t[15]); @@ -343,13 +343,13 @@ namespace Org.BouncyCastle.Crypto.Engines } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector64<byte> Load64(Span<byte> t) + private static Vector64<byte> Load64(ReadOnlySpan<byte> t) { #if NET7_0_OR_GREATER return Vector64.Create<byte>(t); #else if (BitConverter.IsLittleEndian && Unsafe.SizeOf<Vector64<byte>>() == 8) - return Unsafe.ReadUnaligned<Vector64<byte>>(ref t[0]); + return Unsafe.ReadUnaligned<Vector64<byte>>(ref Unsafe.AsRef(t[0])); return Vector64.Create(t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7]); #endif @@ -369,7 +369,7 @@ namespace Org.BouncyCastle.Crypto.Engines var u = s.AsUInt64(); Utilities.Pack.UInt64_To_LE(u.GetElement(0), t); - Utilities.Pack.UInt64_To_LE(u.GetElement(1), t.Slice(8)); + Utilities.Pack.UInt64_To_LE(u.GetElement(1), t[8..]); #endif } } diff --git a/crypto/src/crypto/engines/ChaCha7539Engine.cs b/crypto/src/crypto/engines/ChaCha7539Engine.cs index 81e97478b..d1dd9755b 100644 --- a/crypto/src/crypto/engines/ChaCha7539Engine.cs +++ b/crypto/src/crypto/engines/ChaCha7539Engine.cs @@ -168,7 +168,8 @@ namespace Org.BouncyCastle.Crypto.Engines #if NETCOREAPP3_0_OR_GREATER [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void ImplProcessBlocks2_X86_Avx2(int rounds, uint[] state, Span<byte> input, Span<byte> output) + internal static void ImplProcessBlocks2_X86_Avx2(int rounds, uint[] state, ReadOnlySpan<byte> input, + Span<byte> output) { if (!Avx2.IsSupported) throw new PlatformNotSupportedException(); @@ -244,18 +245,19 @@ namespace Org.BouncyCastle.Crypto.Engines var n3 = Avx2.Permute2x128(v2, v3, 0x31).AsByte(); n0 = Avx2.Xor(n0, Load256_Byte(input)); - n1 = Avx2.Xor(n1, Load256_Byte(input.Slice(0x20))); - n2 = Avx2.Xor(n2, Load256_Byte(input.Slice(0x40))); - n3 = Avx2.Xor(n3, Load256_Byte(input.Slice(0x60))); + n1 = Avx2.Xor(n1, Load256_Byte(input[0x20..])); + n2 = Avx2.Xor(n2, Load256_Byte(input[0x40..])); + n3 = Avx2.Xor(n3, Load256_Byte(input[0x60..])); Store256_Byte(ref n0, output); - Store256_Byte(ref n1, output.Slice(0x20)); - Store256_Byte(ref n2, output.Slice(0x40)); - Store256_Byte(ref n3, output.Slice(0x60)); + Store256_Byte(ref n1, output[0x20..]); + Store256_Byte(ref n2, output[0x40..]); + Store256_Byte(ref n3, output[0x60..]); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void ImplProcessBlocks2_X86_Sse2(int rounds, uint[] state, Span<byte> input, Span<byte> output) + internal static void ImplProcessBlocks2_X86_Sse2(int rounds, uint[] state, ReadOnlySpan<byte> input, + Span<byte> output) { if (!Sse2.IsSupported) throw new PlatformNotSupportedException(); @@ -319,9 +321,9 @@ namespace Org.BouncyCastle.Crypto.Engines v3 = Sse2.Add(v3, x3); var n0 = Load128_Byte(input); - var n1 = Load128_Byte(input.Slice(0x10)); - var n2 = Load128_Byte(input.Slice(0x20)); - var n3 = Load128_Byte(input.Slice(0x30)); + var n1 = Load128_Byte(input[0x10..]); + var n2 = Load128_Byte(input[0x20..]); + var n3 = Load128_Byte(input[0x30..]); n0 = Sse2.Xor(n0, v0.AsByte()); n1 = Sse2.Xor(n1, v1.AsByte()); @@ -329,9 +331,9 @@ namespace Org.BouncyCastle.Crypto.Engines n3 = Sse2.Xor(n3, v3.AsByte()); Store128_Byte(ref n0, output); - Store128_Byte(ref n1, output.Slice(0x10)); - Store128_Byte(ref n2, output.Slice(0x20)); - Store128_Byte(ref n3, output.Slice(0x30)); + Store128_Byte(ref n1, output[0x10..]); + Store128_Byte(ref n2, output[0x20..]); + Store128_Byte(ref n3, output[0x30..]); x3 = Load128_UInt32(state.AsSpan(12)); ++state[12]; @@ -383,46 +385,46 @@ namespace Org.BouncyCastle.Crypto.Engines v2 = Sse2.Add(v2, x2); v3 = Sse2.Add(v3, x3); - n0 = Load128_Byte(input.Slice(0x40)); - n1 = Load128_Byte(input.Slice(0x50)); - n2 = Load128_Byte(input.Slice(0x60)); - n3 = Load128_Byte(input.Slice(0x70)); + n0 = Load128_Byte(input[0x40..]); + n1 = Load128_Byte(input[0x50..]); + n2 = Load128_Byte(input[0x60..]); + n3 = Load128_Byte(input[0x70..]); n0 = Sse2.Xor(n0, v0.AsByte()); n1 = Sse2.Xor(n1, v1.AsByte()); n2 = Sse2.Xor(n2, v2.AsByte()); n3 = Sse2.Xor(n3, v3.AsByte()); - Store128_Byte(ref n0, output.Slice(0x40)); - Store128_Byte(ref n1, output.Slice(0x50)); - Store128_Byte(ref n2, output.Slice(0x60)); - Store128_Byte(ref n3, output.Slice(0x70)); + Store128_Byte(ref n0, output[0x40..]); + Store128_Byte(ref n1, output[0x50..]); + Store128_Byte(ref n2, output[0x60..]); + Store128_Byte(ref n3, output[0x70..]); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector128<byte> Load128_Byte(Span<byte> t) + private static Vector128<byte> Load128_Byte(ReadOnlySpan<byte> t) { if (BitConverter.IsLittleEndian && Unsafe.SizeOf<Vector128<byte>>() == 16) - return Unsafe.ReadUnaligned<Vector128<byte>>(ref t[0]); + return Unsafe.ReadUnaligned<Vector128<byte>>(ref Unsafe.AsRef(t[0])); return Vector128.Create(t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8], t[9], t[10], t[11], t[12], t[13], t[14], t[15]); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector128<uint> Load128_UInt32(Span<uint> t) + private static Vector128<uint> Load128_UInt32(ReadOnlySpan<uint> t) { if (BitConverter.IsLittleEndian && Unsafe.SizeOf<Vector128<uint>>() == 16) - return Unsafe.ReadUnaligned<Vector128<uint>>(ref Unsafe.As<uint, byte>(ref t[0])); + return Unsafe.ReadUnaligned<Vector128<uint>>(ref Unsafe.As<uint, byte>(ref Unsafe.AsRef(t[0]))); return Vector128.Create(t[0], t[1], t[2], t[3]); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector256<byte> Load256_Byte(Span<byte> t) + private static Vector256<byte> Load256_Byte(ReadOnlySpan<byte> t) { if (BitConverter.IsLittleEndian && Unsafe.SizeOf<Vector256<byte>>() == 32) - return Unsafe.ReadUnaligned<Vector256<byte>>(ref t[0]); + return Unsafe.ReadUnaligned<Vector256<byte>>(ref Unsafe.AsRef(t[0])); return Vector256.Create(t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8], t[9], t[10], t[11], t[12], t[13], t[14], t[15], t[16], t[17], t[18], t[19], t[20], t[21], t[22], t[23], t[24], t[25], t[26], t[27], @@ -440,7 +442,7 @@ namespace Org.BouncyCastle.Crypto.Engines var u = s.AsUInt64(); Pack.UInt64_To_LE(u.GetElement(0), t); - Pack.UInt64_To_LE(u.GetElement(1), t.Slice(8)); + Pack.UInt64_To_LE(u.GetElement(1), t[8..]); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -454,9 +456,9 @@ namespace Org.BouncyCastle.Crypto.Engines var u = s.AsUInt64(); Pack.UInt64_To_LE(u.GetElement(0), t); - Pack.UInt64_To_LE(u.GetElement(1), t.Slice(8)); - Pack.UInt64_To_LE(u.GetElement(2), t.Slice(16)); - Pack.UInt64_To_LE(u.GetElement(3), t.Slice(24)); + Pack.UInt64_To_LE(u.GetElement(1), t[8..]); + Pack.UInt64_To_LE(u.GetElement(2), t[16..]); + Pack.UInt64_To_LE(u.GetElement(3), t[24..]); } #endif } diff --git a/crypto/src/crypto/engines/ChaChaEngine.cs b/crypto/src/crypto/engines/ChaChaEngine.cs index a16491ba0..646a6976c 100644 --- a/crypto/src/crypto/engines/ChaChaEngine.cs +++ b/crypto/src/crypto/engines/ChaChaEngine.cs @@ -213,10 +213,10 @@ namespace Org.BouncyCastle.Crypto.Engines #if NETCOREAPP3_0_OR_GREATER [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector128<uint> Load128_UInt32(Span<uint> t) + private static Vector128<uint> Load128_UInt32(ReadOnlySpan<uint> t) { if (BitConverter.IsLittleEndian && Unsafe.SizeOf<Vector128<uint>>() == 16) - return Unsafe.ReadUnaligned<Vector128<uint>>(ref Unsafe.As<uint, byte>(ref t[0])); + return Unsafe.ReadUnaligned<Vector128<uint>>(ref Unsafe.As<uint, byte>(ref Unsafe.AsRef(t[0]))); return Vector128.Create(t[0], t[1], t[2], t[3]); } @@ -232,7 +232,7 @@ namespace Org.BouncyCastle.Crypto.Engines var u = s.AsUInt64(); Pack.UInt64_To_LE(u.GetElement(0), t); - Pack.UInt64_To_LE(u.GetElement(1), t.Slice(8)); + Pack.UInt64_To_LE(u.GetElement(1), t[8..]); } #endif } diff --git a/crypto/src/crypto/engines/ThreefishEngine.cs b/crypto/src/crypto/engines/ThreefishEngine.cs index eade3cc72..c5aee5395 100644 --- a/crypto/src/crypto/engines/ThreefishEngine.cs +++ b/crypto/src/crypto/engines/ThreefishEngine.cs @@ -135,18 +135,17 @@ namespace Org.BouncyCastle.Crypto.Engines switch (blocksizeBits) { - case BLOCKSIZE_256: + case BLOCKSIZE_256: cipher = new Threefish256Cipher(kw, t); break; - case BLOCKSIZE_512: + case BLOCKSIZE_512: cipher = new Threefish512Cipher(kw, t); break; - case BLOCKSIZE_1024: + case BLOCKSIZE_1024: cipher = new Threefish1024Cipher(kw, t); break; - default: - throw new ArgumentException( - "Invalid blocksize - Threefish is defined with block size of 256, 512, or 1024 bits"); + default: + throw new ArgumentException("Invalid blocksize - Threefish is defined with block size of 256, 512, or 1024 bits"); } } @@ -189,10 +188,7 @@ namespace Org.BouncyCastle.Crypto.Engines + " bytes)"); } keyWords = new ulong[blocksizeWords]; - for (int i = 0; i < keyWords.Length; i++) - { - keyWords[i] = BytesToWord(keyBytes, i * 8); - } + Pack.LE_To_UInt64(keyBytes, 0, keyWords); } if (tweakBytes != null) { @@ -200,7 +196,8 @@ namespace Org.BouncyCastle.Crypto.Engines { throw new ArgumentException("Threefish tweak must be " + TWEAK_SIZE_BYTES + " bytes"); } - tweakWords = new ulong[]{BytesToWord(tweakBytes, 0), BytesToWord(tweakBytes, 8)}; + tweakWords = new ulong[2]; + Pack.LE_To_UInt64(tweakBytes, 0, tweakWords); } Init(forEncryption, keyWords, tweakWords); } @@ -298,16 +295,9 @@ namespace Org.BouncyCastle.Crypto.Engines throw new DataLengthException("Input buffer too short"); } - for (int i = 0; i < blocksizeBytes; i += 8) - { - currentBlock[i >> 3] = BytesToWord(inBytes, inOff + i); - } + Pack.LE_To_UInt64(inBytes, inOff, currentBlock); ProcessBlock(this.currentBlock, this.currentBlock); - for (int i = 0; i < blocksizeBytes; i += 8) - { - WordToBytes(this.currentBlock[i >> 3], outBytes, outOff + i); - } - + Pack.UInt64_To_LE(currentBlock, outBytes, outOff); return blocksizeBytes; } @@ -347,54 +337,6 @@ namespace Org.BouncyCastle.Crypto.Engines return blocksizeWords; } - /// <summary> - /// Read a single 64 bit word from input in LSB first order. - /// </summary> - internal static ulong BytesToWord(byte[] bytes, int off) - { - if ((off + 8) > bytes.Length) - { - // Help the JIT avoid index checks - throw new ArgumentException(); - } - - ulong word = 0; - int index = off; - - word = (bytes[index++] & 0xffUL); - word |= (bytes[index++] & 0xffUL) << 8; - word |= (bytes[index++] & 0xffUL) << 16; - word |= (bytes[index++] & 0xffUL) << 24; - word |= (bytes[index++] & 0xffUL) << 32; - word |= (bytes[index++] & 0xffUL) << 40; - word |= (bytes[index++] & 0xffUL) << 48; - word |= (bytes[index++] & 0xffUL) << 56; - - return word; - } - - /// <summary> - /// Write a 64 bit word to output in LSB first order. - /// </summary> - internal static void WordToBytes(ulong word, byte[] bytes, int off) - { - if ((off + 8) > bytes.Length) - { - // Help the JIT avoid index checks - throw new ArgumentException(); - } - int index = off; - - bytes[index++] = (byte)word; - bytes[index++] = (byte)(word >> 8); - bytes[index++] = (byte)(word >> 16); - bytes[index++] = (byte)(word >> 24); - bytes[index++] = (byte)(word >> 32); - bytes[index++] = (byte)(word >> 40); - bytes[index++] = (byte)(word >> 48); - bytes[index++] = (byte)(word >> 56); - } - /** * Rotate left + xor part of the mix operation. */ diff --git a/crypto/src/crypto/operators/DefaultSignatureResult.cs b/crypto/src/crypto/operators/DefaultSignatureResult.cs index 615f67dcb..a236838d6 100644 --- a/crypto/src/crypto/operators/DefaultSignatureResult.cs +++ b/crypto/src/crypto/operators/DefaultSignatureResult.cs @@ -23,5 +23,14 @@ namespace Org.BouncyCastle.Crypto.Operators signature.CopyTo(sig, sigOff); return signature.Length; } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public int Collect(Span<byte> destination) + { + byte[] result = Collect(); + result.CopyTo(destination); + return result.Length; + } +#endif } } diff --git a/crypto/src/math/ec/custom/sec/SecT113Field.cs b/crypto/src/math/ec/custom/sec/SecT113Field.cs index c41d9f7d7..65249562a 100644 --- a/crypto/src/math/ec/custom/sec/SecT113Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT113Field.cs @@ -1,5 +1,9 @@ using System; using System.Diagnostics; +#if NETCOREAPP3_0_OR_GREATER +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +#endif using Org.BouncyCastle.Math.Raw; @@ -166,6 +170,25 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) { +#if NETCOREAPP3_0_OR_GREATER + if (Pclmulqdq.IsSupported) + { + var X01 = Vector128.Create(x[0], x[1]); + var Y01 = Vector128.Create(y[0], y[1]); + + var Z01 = Pclmulqdq.CarrylessMultiply(X01, Y01, 0x00); + var Z12 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y01, 0x01), + Pclmulqdq.CarrylessMultiply(X01, Y01, 0x10)); + var Z23 = Pclmulqdq.CarrylessMultiply(X01, Y01, 0x11); + + zz[0] = Z01.GetElement(0); + zz[1] = Z01.GetElement(1) ^ Z12.GetElement(0); + zz[2] = Z23.GetElement(0) ^ Z12.GetElement(1); + zz[3] = Z23.GetElement(1); + return; + } +#endif + /* * "Three-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein. */ diff --git a/crypto/src/math/ec/custom/sec/SecT131Field.cs b/crypto/src/math/ec/custom/sec/SecT131Field.cs index 4ff5999a4..6088b264c 100644 --- a/crypto/src/math/ec/custom/sec/SecT131Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT131Field.cs @@ -1,5 +1,9 @@ using System; using System.Diagnostics; +#if NETCOREAPP3_0_OR_GREATER +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +#endif using Org.BouncyCastle.Math.Raw; @@ -194,6 +198,33 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) { +#if NETCOREAPP3_0_OR_GREATER + if (Pclmulqdq.IsSupported) + { + var X01 = Vector128.Create(x[0], x[1]); + var X2_ = Vector128.CreateScalar(x[2]); + var Y01 = Vector128.Create(y[0], y[1]); + var Y2_ = Vector128.CreateScalar(y[2]); + + var Z01 = Pclmulqdq.CarrylessMultiply(X01, Y01, 0x00); + var Z12 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y01, 0x01), + Pclmulqdq.CarrylessMultiply(X01, Y01, 0x10)); + var Z23 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y2_, 0x00), + Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y01, 0x11), + Pclmulqdq.CarrylessMultiply(X2_, Y01, 0x00))); + var Z34 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y2_, 0x01), + Pclmulqdq.CarrylessMultiply(X2_, Y01, 0x10)); + var Z4_ = Pclmulqdq.CarrylessMultiply(X2_, Y2_, 0x00); + + zz[0] = Z01.GetElement(0); + zz[1] = Z01.GetElement(1) ^ Z12.GetElement(0); + zz[2] = Z23.GetElement(0) ^ Z12.GetElement(1); + zz[3] = Z23.GetElement(1) ^ Z34.GetElement(0); + zz[4] = Z4_.GetElement(0) ^ Z34.GetElement(1); + return; + } +#endif + /* * "Five-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein. */ diff --git a/crypto/src/math/ec/custom/sec/SecT163Field.cs b/crypto/src/math/ec/custom/sec/SecT163Field.cs index 44105039d..0c616600a 100644 --- a/crypto/src/math/ec/custom/sec/SecT163Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT163Field.cs @@ -1,5 +1,9 @@ using System; using System.Diagnostics; +#if NETCOREAPP3_0_OR_GREATER +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +#endif using Org.BouncyCastle.Math.Raw; @@ -205,6 +209,34 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) { +#if NETCOREAPP3_0_OR_GREATER + if (Pclmulqdq.IsSupported) + { + var X01 = Vector128.Create(x[0], x[1]); + var X2_ = Vector128.CreateScalar(x[2]); + var Y01 = Vector128.Create(y[0], y[1]); + var Y2_ = Vector128.CreateScalar(y[2]); + + var Z01 = Pclmulqdq.CarrylessMultiply(X01, Y01, 0x00); + var Z12 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y01, 0x01), + Pclmulqdq.CarrylessMultiply(X01, Y01, 0x10)); + var Z23 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y2_, 0x00), + Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y01, 0x11), + Pclmulqdq.CarrylessMultiply(X2_, Y01, 0x00))); + var Z34 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y2_, 0x01), + Pclmulqdq.CarrylessMultiply(X2_, Y01, 0x10)); + var Z45 = Pclmulqdq.CarrylessMultiply(X2_, Y2_, 0x00); + + zz[0] = Z01.GetElement(0); + zz[1] = Z01.GetElement(1) ^ Z12.GetElement(0); + zz[2] = Z23.GetElement(0) ^ Z12.GetElement(1); + zz[3] = Z23.GetElement(1) ^ Z34.GetElement(0); + zz[4] = Z45.GetElement(0) ^ Z34.GetElement(1); + zz[5] = Z45.GetElement(1); + return; + } +#endif + /* * "Five-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein. */ diff --git a/crypto/src/math/ec/custom/sec/SecT193Field.cs b/crypto/src/math/ec/custom/sec/SecT193Field.cs index 59da8b000..4aa3ad5c2 100644 --- a/crypto/src/math/ec/custom/sec/SecT193Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT193Field.cs @@ -1,5 +1,9 @@ using System; using System.Diagnostics; +#if NETCOREAPP3_0_OR_GREATER +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +#endif using Org.BouncyCastle.Math.Raw; @@ -226,6 +230,38 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) { +#if NETCOREAPP3_0_OR_GREATER + if (Pclmulqdq.IsSupported) + { + var X01 = Vector128.Create(x[0], x[1]); + var X2_ = Vector128.CreateScalar(x[2]); + var Y01 = Vector128.Create(y[0], y[1]); + var Y2_ = Vector128.CreateScalar(y[2]); + + var Z01 = Pclmulqdq.CarrylessMultiply(X01, Y01, 0x00); + var Z12 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y01, 0x01), + Pclmulqdq.CarrylessMultiply(X01, Y01, 0x10)); + var Z23 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y2_, 0x00), + Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y01, 0x11), + Pclmulqdq.CarrylessMultiply(X2_, Y01, 0x00))); + var Z34 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y2_, 0x01), + Pclmulqdq.CarrylessMultiply(X2_, Y01, 0x10)); + var Z45 = Pclmulqdq.CarrylessMultiply(X2_, Y2_, 0x00); + + ulong X3M = 0UL - x[3]; + ulong Y3M = 0UL - y[3]; + + zz[0] = Z01.GetElement(0); + zz[1] = Z01.GetElement(1) ^ Z12.GetElement(0); + zz[2] = Z23.GetElement(0) ^ Z12.GetElement(1); + zz[3] = Z23.GetElement(1) ^ Z34.GetElement(0) ^ (X3M & y[0]) ^ (x[0] & Y3M); + zz[4] = Z45.GetElement(0) ^ Z34.GetElement(1) ^ (X3M & y[1]) ^ (x[1] & Y3M); + zz[5] = Z45.GetElement(1) ^ (X3M & y[2]) ^ (x[2] & Y3M); + zz[6] = X3M & y[3]; + return; + } +#endif + /* * "Two-level seven-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein. */ diff --git a/crypto/src/math/ec/custom/sec/SecT233Field.cs b/crypto/src/math/ec/custom/sec/SecT233Field.cs index c16a3d612..e4e291154 100644 --- a/crypto/src/math/ec/custom/sec/SecT233Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT233Field.cs @@ -1,5 +1,9 @@ using System; using System.Diagnostics; +#if NETCOREAPP3_0_OR_GREATER +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +#endif using Org.BouncyCastle.Math.Raw; @@ -237,6 +241,54 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) { +#if NETCOREAPP3_0_OR_GREATER + if (Pclmulqdq.IsSupported) + { + var X01 = Vector128.Create(x[0], x[1]); + var X23 = Vector128.Create(x[2], x[3]); + var Y01 = Vector128.Create(y[0], y[1]); + var Y23 = Vector128.Create(y[2], y[3]); + var X03 = Sse2.Xor(X01, X23); + var Y03 = Sse2.Xor(Y01, Y23); + + var Z01 = Pclmulqdq.CarrylessMultiply(X01, Y01, 0x00); + var Z12 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y01, 0x01), + Pclmulqdq.CarrylessMultiply(X01, Y01, 0x10)); + var Z23 = Pclmulqdq.CarrylessMultiply(X01, Y01, 0x11); + + var Z45 = Pclmulqdq.CarrylessMultiply(X23, Y23, 0x00); + var Z56 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X23, Y23, 0x01), + Pclmulqdq.CarrylessMultiply(X23, Y23, 0x10)); + var Z67 = Pclmulqdq.CarrylessMultiply(X23, Y23, 0x11); + + var K01 = Pclmulqdq.CarrylessMultiply(X03, Y03, 0x00); + var K12 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X03, Y03, 0x01), + Pclmulqdq.CarrylessMultiply(X03, Y03, 0x10)); + var K23 = Pclmulqdq.CarrylessMultiply(X03, Y03, 0x11); + + K01 = Sse2.Xor(K01, Z01); + K12 = Sse2.Xor(K12, Z12); + K23 = Sse2.Xor(K23, Z23); + + K01 = Sse2.Xor(K01, Z45); + K12 = Sse2.Xor(K12, Z56); + K23 = Sse2.Xor(K23, Z67); + + Z23 = Sse2.Xor(Z23, K01); + Z45 = Sse2.Xor(Z45, K23); + + zz[0] = Z01.GetElement(0); + zz[1] = Z01.GetElement(1) ^ Z12.GetElement(0); + zz[2] = Z23.GetElement(0) ^ Z12.GetElement(1); + zz[3] = Z23.GetElement(1) ^ K12.GetElement(0); + zz[4] = Z45.GetElement(0) ^ K12.GetElement(1); + zz[5] = Z45.GetElement(1) ^ Z56.GetElement(0); + zz[6] = Z67.GetElement(0) ^ Z56.GetElement(1); + zz[7] = Z67.GetElement(1); + return; + } +#endif + /* * "Two-level seven-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein. */ diff --git a/crypto/src/math/ec/custom/sec/SecT239Field.cs b/crypto/src/math/ec/custom/sec/SecT239Field.cs index de87b18a2..a3851de16 100644 --- a/crypto/src/math/ec/custom/sec/SecT239Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT239Field.cs @@ -1,5 +1,9 @@ using System; using System.Diagnostics; +#if NETCOREAPP3_0_OR_GREATER +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +#endif using Org.BouncyCastle.Math.Raw; @@ -246,6 +250,54 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) { +#if NETCOREAPP3_0_OR_GREATER + if (Pclmulqdq.IsSupported) + { + var X01 = Vector128.Create(x[0], x[1]); + var X23 = Vector128.Create(x[2], x[3]); + var Y01 = Vector128.Create(y[0], y[1]); + var Y23 = Vector128.Create(y[2], y[3]); + var X03 = Sse2.Xor(X01, X23); + var Y03 = Sse2.Xor(Y01, Y23); + + var Z01 = Pclmulqdq.CarrylessMultiply(X01, Y01, 0x00); + var Z12 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y01, 0x01), + Pclmulqdq.CarrylessMultiply(X01, Y01, 0x10)); + var Z23 = Pclmulqdq.CarrylessMultiply(X01, Y01, 0x11); + + var Z45 = Pclmulqdq.CarrylessMultiply(X23, Y23, 0x00); + var Z56 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X23, Y23, 0x01), + Pclmulqdq.CarrylessMultiply(X23, Y23, 0x10)); + var Z67 = Pclmulqdq.CarrylessMultiply(X23, Y23, 0x11); + + var K01 = Pclmulqdq.CarrylessMultiply(X03, Y03, 0x00); + var K12 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X03, Y03, 0x01), + Pclmulqdq.CarrylessMultiply(X03, Y03, 0x10)); + var K23 = Pclmulqdq.CarrylessMultiply(X03, Y03, 0x11); + + K01 = Sse2.Xor(K01, Z01); + K12 = Sse2.Xor(K12, Z12); + K23 = Sse2.Xor(K23, Z23); + + K01 = Sse2.Xor(K01, Z45); + K12 = Sse2.Xor(K12, Z56); + K23 = Sse2.Xor(K23, Z67); + + Z23 = Sse2.Xor(Z23, K01); + Z45 = Sse2.Xor(Z45, K23); + + zz[0] = Z01.GetElement(0); + zz[1] = Z01.GetElement(1) ^ Z12.GetElement(0); + zz[2] = Z23.GetElement(0) ^ Z12.GetElement(1); + zz[3] = Z23.GetElement(1) ^ K12.GetElement(0); + zz[4] = Z45.GetElement(0) ^ K12.GetElement(1); + zz[5] = Z45.GetElement(1) ^ Z56.GetElement(0); + zz[6] = Z67.GetElement(0) ^ Z56.GetElement(1); + zz[7] = Z67.GetElement(1); + return; + } +#endif + /* * "Two-level seven-way recursion" as described in "Batch binary Edwards", Daniel J. Bernstein. */ diff --git a/crypto/src/math/ec/custom/sec/SecT283Field.cs b/crypto/src/math/ec/custom/sec/SecT283Field.cs index ee5ad89c5..334986452 100644 --- a/crypto/src/math/ec/custom/sec/SecT283Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT283Field.cs @@ -1,5 +1,9 @@ using System; using System.Diagnostics; +#if NETCOREAPP3_0_OR_GREATER +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +#endif using Org.BouncyCastle.Math.Raw; @@ -245,6 +249,56 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec protected static void ImplMultiply(ulong[] x, ulong[] y, ulong[] zz) { +#if NETCOREAPP3_0_OR_GREATER + if (Pclmulqdq.IsSupported) + { + var X01 = Vector128.Create(x[0], x[1]); + var X23 = Vector128.Create(x[2], x[3]); + var X4_ = Vector128.CreateScalar(x[4]); + var Y01 = Vector128.Create(y[0], y[1]); + var Y23 = Vector128.Create(y[2], y[3]); + var Y4_ = Vector128.CreateScalar(y[4]); + + var Z01 = Pclmulqdq.CarrylessMultiply(X01, Y01, 0x00); + var Z12 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y01, 0x01), + Pclmulqdq.CarrylessMultiply(X01, Y01, 0x10)); + var Z23 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y23, 0x00), + Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y01, 0x11), + Pclmulqdq.CarrylessMultiply(X23, Y01, 0x00))); + var Z34 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y23, 0x01), + Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y23, 0x10), + Sse2.Xor(Pclmulqdq.CarrylessMultiply(X23, Y01, 0x01), + Pclmulqdq.CarrylessMultiply(X23, Y01, 0x10)))); + var Z45 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y4_, 0x00), + Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y23, 0x11), + Sse2.Xor(Pclmulqdq.CarrylessMultiply(X23, Y23, 0x00), + Sse2.Xor(Pclmulqdq.CarrylessMultiply(X23, Y01, 0x11), + Pclmulqdq.CarrylessMultiply(X4_, Y01, 0x00))))); + var Z56 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X01, Y4_, 0x01), + Sse2.Xor(Pclmulqdq.CarrylessMultiply(X23, Y23, 0x01), + Sse2.Xor(Pclmulqdq.CarrylessMultiply(X23, Y23, 0x10), + Pclmulqdq.CarrylessMultiply(X4_, Y01, 0x10)))); + var Z67 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X23, Y4_, 0x00), + Sse2.Xor(Pclmulqdq.CarrylessMultiply(X23, Y23, 0x11), + Pclmulqdq.CarrylessMultiply(X4_, Y23, 0x00))); + var Z78 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X23, Y4_, 0x01), + Pclmulqdq.CarrylessMultiply(X4_, Y23, 0x10)); + var Z89 = Pclmulqdq.CarrylessMultiply(X4_, Y4_, 0x00); + + zz[0] = Z01.GetElement(0); + zz[1] = Z01.GetElement(1) ^ Z12.GetElement(0); + zz[2] = Z23.GetElement(0) ^ Z12.GetElement(1); + zz[3] = Z23.GetElement(1) ^ Z34.GetElement(0); + zz[4] = Z45.GetElement(0) ^ Z34.GetElement(1); + zz[5] = Z45.GetElement(1) ^ Z56.GetElement(0); + zz[6] = Z67.GetElement(0) ^ Z56.GetElement(1); + zz[7] = Z67.GetElement(1) ^ Z78.GetElement(0); + zz[8] = Z89.GetElement(0) ^ Z78.GetElement(1); + zz[9] = Z89.GetElement(1); + return; + } +#endif + /* * Formula (17) from "Some New Results on Binary Polynomial Multiplication", * Murat Cenk and M. Anwar Hasan. diff --git a/crypto/src/math/ec/custom/sec/SecT409Field.cs b/crypto/src/math/ec/custom/sec/SecT409Field.cs index 0fb7377f6..414a094a8 100644 --- a/crypto/src/math/ec/custom/sec/SecT409Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT409Field.cs @@ -1,5 +1,9 @@ using System; using System.Diagnostics; +#if NETCOREAPP3_0_OR_GREATER +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +#endif using Org.BouncyCastle.Math.Raw; @@ -344,6 +348,20 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec Debug.Assert(x >> 59 == 0); Debug.Assert(y >> 59 == 0); +#if NETCOREAPP3_0_OR_GREATER + if (Pclmulqdq.IsSupported) + { + var X = Vector128.CreateScalar(x); + var Y = Vector128.CreateScalar(y); + var Z = Pclmulqdq.CarrylessMultiply(X, Y, 0x00); + ulong z0 = Z.GetElement(0); + ulong z1 = Z.GetElement(1); + z[zOff ] ^= z0 & M59; + z[zOff + 1] ^= (z0 >> 59) ^ (z1 << 5); + return; + } +#endif + //u[0] = 0; u[1] = y; u[2] = u[1] << 1; diff --git a/crypto/src/math/ec/custom/sec/SecT571Field.cs b/crypto/src/math/ec/custom/sec/SecT571Field.cs index 91a3fde9d..5a393409a 100644 --- a/crypto/src/math/ec/custom/sec/SecT571Field.cs +++ b/crypto/src/math/ec/custom/sec/SecT571Field.cs @@ -175,6 +175,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec public static ulong[] PrecompMultiplicand(ulong[] x) { +#if NETCOREAPP3_0_OR_GREATER + ulong[] z = Nat576.Create64(); + Nat576.Copy64(x, z); + return z; +#else /* * Precompute table of all 4-bit products of x (first section) */ @@ -197,6 +202,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec Nat.ShiftUpBits64(len, t, 0, 4, 0UL, t, len); return t; +#endif } public static void Reduce(ulong[] xx, ulong[] z) @@ -367,6 +373,9 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec protected static void ImplMultiplyPrecomp(ulong[] x, ulong[] precomp, ulong[] zz) { +#if NETCOREAPP3_0_OR_GREATER + ImplMultiply(x, precomp, zz); +#else uint MASK = 0xF; /* @@ -399,6 +408,7 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec Nat.ShiftUpBits64(18, zz, 0, 8, 0UL); } } +#endif } protected static void ImplMulwAcc(ulong[] u, ulong x, ulong y, ulong[] z, int zOff) diff --git a/crypto/src/ocsp/BasicOCSPRespGenerator.cs b/crypto/src/ocsp/BasicOCSPRespGenerator.cs index d4ec3df80..63d577404 100644 --- a/crypto/src/ocsp/BasicOCSPRespGenerator.cs +++ b/crypto/src/ocsp/BasicOCSPRespGenerator.cs @@ -32,30 +32,11 @@ namespace Org.BouncyCastle.Ocsp internal DerGeneralizedTime nextUpdate; internal X509Extensions extensions; - public ResponseObject( + internal ResponseObject( CertificateID certId, CertificateStatus certStatus, DateTime thisUpdate, - X509Extensions extensions) - : this(certId, certStatus, new DerGeneralizedTime(thisUpdate), null, extensions) - { - } - - public ResponseObject( - CertificateID certId, - CertificateStatus certStatus, - DateTime thisUpdate, - DateTime nextUpdate, - X509Extensions extensions) - : this(certId, certStatus, new DerGeneralizedTime(thisUpdate), new DerGeneralizedTime(nextUpdate), extensions) - { - } - - private ResponseObject( - CertificateID certId, - CertificateStatus certStatus, - DerGeneralizedTime thisUpdate, - DerGeneralizedTime nextUpdate, + DateTime? nextUpdate, X509Extensions extensions) { this.certId = certId; @@ -79,8 +60,8 @@ namespace Org.BouncyCastle.Ocsp new RevokedInfo(new DerGeneralizedTime(rs.RevocationTime), revocationReason)); } - this.thisUpdate = thisUpdate; - this.nextUpdate = nextUpdate; + this.thisUpdate = new DerGeneralizedTime(thisUpdate); + this.nextUpdate = nextUpdate.HasValue ? new DerGeneralizedTime(nextUpdate.Value) : null; this.extensions = extensions; } @@ -119,7 +100,7 @@ namespace Org.BouncyCastle.Ocsp CertificateID certID, CertificateStatus certStatus) { - list.Add(new ResponseObject(certID, certStatus, DateTime.UtcNow, null)); + list.Add(new ResponseObject(certID, certStatus, DateTime.UtcNow, null, null)); } /** @@ -134,7 +115,7 @@ namespace Org.BouncyCastle.Ocsp CertificateStatus certStatus, X509Extensions singleExtensions) { - list.Add(new ResponseObject(certID, certStatus, DateTime.UtcNow, singleExtensions)); + list.Add(new ResponseObject(certID, certStatus, DateTime.UtcNow, null, singleExtensions)); } /** @@ -148,7 +129,7 @@ namespace Org.BouncyCastle.Ocsp public void AddResponse( CertificateID certID, CertificateStatus certStatus, - DateTime nextUpdate, + DateTime? nextUpdate, X509Extensions singleExtensions) { list.Add(new ResponseObject(certID, certStatus, DateTime.UtcNow, nextUpdate, singleExtensions)); @@ -167,7 +148,7 @@ namespace Org.BouncyCastle.Ocsp CertificateID certID, CertificateStatus certStatus, DateTime thisUpdate, - DateTime nextUpdate, + DateTime? nextUpdate, X509Extensions singleExtensions) { list.Add(new ResponseObject(certID, certStatus, thisUpdate, nextUpdate, singleExtensions)); @@ -230,7 +211,7 @@ namespace Org.BouncyCastle.Ocsp DerSequence chainSeq = null; if (chain != null && chain.Length > 0) { - Asn1EncodableVector v = new Asn1EncodableVector(); + Asn1EncodableVector v = new Asn1EncodableVector(chain.Length); try { for (int i = 0; i != chain.Length; i++) diff --git a/crypto/src/tls/AbstractTlsContext.cs b/crypto/src/tls/AbstractTlsContext.cs index be7a67dfc..a5ac85962 100644 --- a/crypto/src/tls/AbstractTlsContext.cs +++ b/crypto/src/tls/AbstractTlsContext.cs @@ -170,6 +170,9 @@ namespace Org.BouncyCastle.Tls SecurityParameters securityParameters = SecurityParameters; + if (ChannelBinding.tls_exporter == channelBinding) + return ExportKeyingMaterial("EXPORTER-Channel-Binding", TlsUtilities.EmptyBytes, 32); + if (TlsUtilities.IsTlsV13(securityParameters.NegotiatedVersion)) return null; diff --git a/crypto/src/tls/ChannelBinding.cs b/crypto/src/tls/ChannelBinding.cs index 84f8bc4df..d6e0cbe27 100644 --- a/crypto/src/tls/ChannelBinding.cs +++ b/crypto/src/tls/ChannelBinding.cs @@ -15,5 +15,10 @@ namespace Org.BouncyCastle.Tls public const int tls_server_end_point = 0; public const int tls_unique = 1; public const int tls_unique_for_telnet = 2; + + /* + * RFC 9266 + */ + public const int tls_exporter = 3; } } diff --git a/crypto/test/src/tls/test/MockTlsClient.cs b/crypto/test/src/tls/test/MockTlsClient.cs index 98898dd30..731504757 100644 --- a/crypto/test/src/tls/test/MockTlsClient.cs +++ b/crypto/test/src/tls/test/MockTlsClient.cs @@ -127,6 +127,9 @@ namespace Org.BouncyCastle.Tls.Tests byte[] tlsUnique = m_context.ExportChannelBinding(ChannelBinding.tls_unique); Console.WriteLine("Client 'tls-unique': " + ToHexString(tlsUnique)); + + byte[] tlsExporter = m_context.ExportChannelBinding(ChannelBinding.tls_exporter); + Console.WriteLine("Client 'tls-exporter': " + ToHexString(tlsExporter)); } } diff --git a/crypto/test/src/tls/test/MockTlsServer.cs b/crypto/test/src/tls/test/MockTlsServer.cs index d4e885117..c4aa2c74d 100644 --- a/crypto/test/src/tls/test/MockTlsServer.cs +++ b/crypto/test/src/tls/test/MockTlsServer.cs @@ -155,6 +155,9 @@ namespace Org.BouncyCastle.Tls.Tests byte[] tlsUnique = m_context.ExportChannelBinding(ChannelBinding.tls_unique); Console.WriteLine("Server 'tls-unique': " + ToHexString(tlsUnique)); + + byte[] tlsExporter = m_context.ExportChannelBinding(ChannelBinding.tls_exporter); + Console.WriteLine("Server 'tls-exporter': " + ToHexString(tlsExporter)); } public override void ProcessClientExtensions(IDictionary<int, byte[]> clientExtensions) |