835 lines
30 KiB
C#
835 lines
30 KiB
C#
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
|
#pragma warning disable
|
|
#if NETCOREAPP3_0_OR_GREATER
|
|
using System;
|
|
using System.Buffers.Binary;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
using System.Runtime.Intrinsics;
|
|
|
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
|
|
|
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines
|
|
{
|
|
using Aes = System.Runtime.Intrinsics.X86.Aes;
|
|
using Sse2 = System.Runtime.Intrinsics.X86.Sse2;
|
|
|
|
public struct AesEngine_X86
|
|
: IBlockCipher
|
|
{
|
|
public static bool IsSupported => Aes.IsSupported;
|
|
|
|
private static Vector128<byte>[] CreateRoundKeys(byte[] key, bool forEncryption)
|
|
{
|
|
Vector128<byte>[] K;
|
|
|
|
switch (key.Length)
|
|
{
|
|
case 16:
|
|
{
|
|
ReadOnlySpan<byte> rcon = stackalloc byte[]{ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
|
|
|
|
K = new Vector128<byte>[11];
|
|
|
|
var s = Load128(key.AsSpan(0, 16));
|
|
K[0] = s;
|
|
|
|
for (int round = 0; round < 10;)
|
|
{
|
|
var t = Aes.KeygenAssist(s, rcon[round++]);
|
|
t = Sse2.Shuffle(t.AsInt32(), 0xFF).AsByte();
|
|
s = Sse2.Xor(s, Sse2.ShiftLeftLogical128BitLane(s, 8));
|
|
s = Sse2.Xor(s, Sse2.ShiftLeftLogical128BitLane(s, 4));
|
|
s = Sse2.Xor(s, t);
|
|
K[round] = s;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case 24:
|
|
{
|
|
K = new Vector128<byte>[13];
|
|
|
|
var s1 = Load128(key.AsSpan(0, 16));
|
|
var s2 = Load64(key.AsSpan(16, 8)).ToVector128();
|
|
K[0] = s1;
|
|
|
|
byte rcon = 0x01;
|
|
for (int round = 0;;)
|
|
{
|
|
var t1 = Aes.KeygenAssist(s2, rcon); rcon <<= 1;
|
|
t1 = Sse2.Shuffle(t1.AsInt32(), 0x55).AsByte();
|
|
|
|
s1 = Sse2.Xor(s1, Sse2.ShiftLeftLogical128BitLane(s1, 8));
|
|
s1 = Sse2.Xor(s1, Sse2.ShiftLeftLogical128BitLane(s1, 4));
|
|
s1 = Sse2.Xor(s1, t1);
|
|
|
|
K[++round] = Sse2.Xor(s2, Sse2.ShiftLeftLogical128BitLane(s1, 8));
|
|
|
|
var s3 = Sse2.Xor(s2, Sse2.ShiftRightLogical128BitLane(s1, 12));
|
|
s3 = Sse2.Xor(s3, Sse2.ShiftLeftLogical128BitLane(s3, 4));
|
|
|
|
K[++round] = Sse2.Xor(
|
|
Sse2.ShiftRightLogical128BitLane(s1, 8),
|
|
Sse2.ShiftLeftLogical128BitLane(s3, 8));
|
|
|
|
var t2 = Aes.KeygenAssist(s3, rcon); rcon <<= 1;
|
|
t2 = Sse2.Shuffle(t2.AsInt32(), 0x55).AsByte();
|
|
|
|
s1 = Sse2.Xor(s1, Sse2.ShiftLeftLogical128BitLane(s1, 8));
|
|
s1 = Sse2.Xor(s1, Sse2.ShiftLeftLogical128BitLane(s1, 4));
|
|
s1 = Sse2.Xor(s1, t2);
|
|
|
|
K[++round] = s1;
|
|
|
|
if (round == 12)
|
|
break;
|
|
|
|
s2 = Sse2.Xor(s3, Sse2.ShiftRightLogical128BitLane(s1, 12));
|
|
s2 = Sse2.Xor(s2, Sse2.ShiftLeftLogical128BitLane(s2, 4));
|
|
s2 = s2.WithUpper(Vector64<byte>.Zero);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case 32:
|
|
{
|
|
K = new Vector128<byte>[15];
|
|
|
|
var s1 = Load128(key.AsSpan(0, 16));
|
|
var s2 = Load128(key.AsSpan(16, 16));
|
|
K[0] = s1;
|
|
K[1] = s2;
|
|
|
|
byte rcon = 0x01;
|
|
for (int round = 1;;)
|
|
{
|
|
var t1 = Aes.KeygenAssist(s2, rcon); rcon <<= 1;
|
|
t1 = Sse2.Shuffle(t1.AsInt32(), 0xFF).AsByte();
|
|
s1 = Sse2.Xor(s1, Sse2.ShiftLeftLogical128BitLane(s1, 8));
|
|
s1 = Sse2.Xor(s1, Sse2.ShiftLeftLogical128BitLane(s1, 4));
|
|
s1 = Sse2.Xor(s1, t1);
|
|
K[++round] = s1;
|
|
|
|
if (round == 14)
|
|
break;
|
|
|
|
var t2 = Aes.KeygenAssist(s1, 0x00);
|
|
t2 = Sse2.Shuffle(t2.AsInt32(), 0xAA).AsByte();
|
|
s2 = Sse2.Xor(s2, Sse2.ShiftLeftLogical128BitLane(s2, 8));
|
|
s2 = Sse2.Xor(s2, Sse2.ShiftLeftLogical128BitLane(s2, 4));
|
|
s2 = Sse2.Xor(s2, t2);
|
|
K[++round] = s2;
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
throw new ArgumentException("Key length not 128/192/256 bits.");
|
|
}
|
|
|
|
if (!forEncryption)
|
|
{
|
|
for (int i = 1, last = K.Length - 1; i < last; ++i)
|
|
{
|
|
K[i] = Aes.InverseMixColumns(K[i]);
|
|
}
|
|
|
|
Array.Reverse(K);
|
|
}
|
|
|
|
return K;
|
|
}
|
|
|
|
private enum Mode { DEC_128, DEC_192, DEC_256, ENC_128, ENC_192, ENC_256, UNINITIALIZED };
|
|
|
|
private Vector128<byte>[] m_roundKeys = null;
|
|
private Mode m_mode = Mode.UNINITIALIZED;
|
|
|
|
public AesEngine_X86()
|
|
{
|
|
if (!IsSupported)
|
|
throw new PlatformNotSupportedException(nameof(AesEngine_X86));
|
|
}
|
|
|
|
public string AlgorithmName => "AES";
|
|
|
|
public int GetBlockSize() => 16;
|
|
|
|
public void Init(bool forEncryption, ICipherParameters parameters)
|
|
{
|
|
if (!(parameters is KeyParameter keyParameter))
|
|
{
|
|
ArgumentNullException.ThrowIfNull(parameters, nameof(parameters));
|
|
throw new ArgumentException("invalid type: " + Org.BouncyCastle.Utilities.Platform.GetTypeName(parameters), nameof(parameters));
|
|
}
|
|
|
|
m_roundKeys = CreateRoundKeys(keyParameter.GetKey(), forEncryption);
|
|
|
|
if (m_roundKeys.Length == 11)
|
|
{
|
|
m_mode = forEncryption ? Mode.ENC_128 : Mode.DEC_128;
|
|
}
|
|
else if (m_roundKeys.Length == 13)
|
|
{
|
|
m_mode = forEncryption ? Mode.ENC_192 : Mode.DEC_192;
|
|
}
|
|
else
|
|
{
|
|
m_mode = forEncryption ? Mode.ENC_256 : Mode.DEC_256;
|
|
}
|
|
}
|
|
|
|
public int ProcessBlock(byte[] inBuf, int inOff, byte[] outBuf, int outOff)
|
|
{
|
|
Check.DataLength(inBuf, inOff, 16, "input buffer too short");
|
|
Check.OutputLength(outBuf, outOff, 16, "output buffer too short");
|
|
|
|
var state = Load128(inBuf.AsSpan(inOff, 16));
|
|
ImplRounds(ref state);
|
|
Store128(state, outBuf.AsSpan(outOff, 16));
|
|
return 16;
|
|
}
|
|
|
|
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");
|
|
|
|
var state = Load128(input[..16]);
|
|
ImplRounds(ref state);
|
|
Store128(state, output[..16]);
|
|
return 16;
|
|
}
|
|
|
|
public int ProcessFourBlocks(ReadOnlySpan<byte> input, Span<byte> output)
|
|
{
|
|
Check.DataLength(input, 64, "input buffer too short");
|
|
Check.OutputLength(output, 64, "output buffer too short");
|
|
|
|
var s1 = Load128(input[..16]);
|
|
var s2 = Load128(input[16..32]);
|
|
var s3 = Load128(input[32..48]);
|
|
var s4 = Load128(input[48..64]);
|
|
ImplRounds(ref s1, ref s2, ref s3, ref s4);
|
|
Store128(s1, output[..16]);
|
|
Store128(s2, output[16..32]);
|
|
Store128(s3, output[32..48]);
|
|
Store128(s4, output[48..64]);
|
|
return 64;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private void ImplRounds(ref Vector128<byte> state)
|
|
{
|
|
switch (m_mode)
|
|
{
|
|
case Mode.DEC_128: Decrypt128(m_roundKeys, ref state); break;
|
|
case Mode.DEC_192: Decrypt192(m_roundKeys, ref state); break;
|
|
case Mode.DEC_256: Decrypt256(m_roundKeys, ref state); break;
|
|
case Mode.ENC_128: Encrypt128(m_roundKeys, ref state); break;
|
|
case Mode.ENC_192: Encrypt192(m_roundKeys, ref state); break;
|
|
case Mode.ENC_256: Encrypt256(m_roundKeys, ref state); break;
|
|
default: throw new InvalidOperationException(nameof(AesEngine_X86) + " not initialised");
|
|
}
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private void ImplRounds(
|
|
ref Vector128<byte> s1, ref Vector128<byte> s2, ref Vector128<byte> s3, ref Vector128<byte> s4)
|
|
{
|
|
switch (m_mode)
|
|
{
|
|
case Mode.DEC_128: DecryptFour128(m_roundKeys, ref s1, ref s2, ref s3, ref s4); break;
|
|
case Mode.DEC_192: DecryptFour192(m_roundKeys, ref s1, ref s2, ref s3, ref s4); break;
|
|
case Mode.DEC_256: DecryptFour256(m_roundKeys, ref s1, ref s2, ref s3, ref s4); break;
|
|
case Mode.ENC_128: EncryptFour128(m_roundKeys, ref s1, ref s2, ref s3, ref s4); break;
|
|
case Mode.ENC_192: EncryptFour192(m_roundKeys, ref s1, ref s2, ref s3, ref s4); break;
|
|
case Mode.ENC_256: EncryptFour256(m_roundKeys, ref s1, ref s2, ref s3, ref s4); break;
|
|
default: throw new InvalidOperationException(nameof(AesEngine_X86) + " not initialised");
|
|
}
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static void Decrypt128(Vector128<byte>[] roundKeys, ref Vector128<byte> state)
|
|
{
|
|
state = Sse2.Xor(state, roundKeys[0]);
|
|
state = Aes.Decrypt(state, roundKeys[1]);
|
|
state = Aes.Decrypt(state, roundKeys[2]);
|
|
state = Aes.Decrypt(state, roundKeys[3]);
|
|
state = Aes.Decrypt(state, roundKeys[4]);
|
|
state = Aes.Decrypt(state, roundKeys[5]);
|
|
state = Aes.Decrypt(state, roundKeys[6]);
|
|
state = Aes.Decrypt(state, roundKeys[7]);
|
|
state = Aes.Decrypt(state, roundKeys[8]);
|
|
state = Aes.Decrypt(state, roundKeys[9]);
|
|
state = Aes.DecryptLast(state, roundKeys[10]);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static void Decrypt192(Vector128<byte>[] roundKeys, ref Vector128<byte> state)
|
|
{
|
|
state = Sse2.Xor(state, roundKeys[0]);
|
|
state = Aes.Decrypt(state, roundKeys[1]);
|
|
state = Aes.Decrypt(state, roundKeys[2]);
|
|
state = Aes.Decrypt(state, roundKeys[3]);
|
|
state = Aes.Decrypt(state, roundKeys[4]);
|
|
state = Aes.Decrypt(state, roundKeys[5]);
|
|
state = Aes.Decrypt(state, roundKeys[6]);
|
|
state = Aes.Decrypt(state, roundKeys[7]);
|
|
state = Aes.Decrypt(state, roundKeys[8]);
|
|
state = Aes.Decrypt(state, roundKeys[9]);
|
|
state = Aes.Decrypt(state, roundKeys[10]);
|
|
state = Aes.Decrypt(state, roundKeys[11]);
|
|
state = Aes.DecryptLast(state, roundKeys[12]);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static void Decrypt256(Vector128<byte>[] roundKeys, ref Vector128<byte> state)
|
|
{
|
|
state = Sse2.Xor(state, roundKeys[0]);
|
|
state = Aes.Decrypt(state, roundKeys[1]);
|
|
state = Aes.Decrypt(state, roundKeys[2]);
|
|
state = Aes.Decrypt(state, roundKeys[3]);
|
|
state = Aes.Decrypt(state, roundKeys[4]);
|
|
state = Aes.Decrypt(state, roundKeys[5]);
|
|
state = Aes.Decrypt(state, roundKeys[6]);
|
|
state = Aes.Decrypt(state, roundKeys[7]);
|
|
state = Aes.Decrypt(state, roundKeys[8]);
|
|
state = Aes.Decrypt(state, roundKeys[9]);
|
|
state = Aes.Decrypt(state, roundKeys[10]);
|
|
state = Aes.Decrypt(state, roundKeys[11]);
|
|
state = Aes.Decrypt(state, roundKeys[12]);
|
|
state = Aes.Decrypt(state, roundKeys[13]);
|
|
state = Aes.DecryptLast(state, roundKeys[14]);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static void DecryptFour128(Vector128<byte>[] rk,
|
|
ref Vector128<byte> s1, ref Vector128<byte> s2, ref Vector128<byte> s3, ref Vector128<byte> s4)
|
|
{
|
|
s1 = Sse2.Xor(s1, rk[0]);
|
|
s2 = Sse2.Xor(s2, rk[0]);
|
|
s3 = Sse2.Xor(s3, rk[0]);
|
|
s4 = Sse2.Xor(s4, rk[0]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[1]);
|
|
s2 = Aes.Decrypt(s2, rk[1]);
|
|
s3 = Aes.Decrypt(s3, rk[1]);
|
|
s4 = Aes.Decrypt(s4, rk[1]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[2]);
|
|
s2 = Aes.Decrypt(s2, rk[2]);
|
|
s3 = Aes.Decrypt(s3, rk[2]);
|
|
s4 = Aes.Decrypt(s4, rk[2]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[3]);
|
|
s2 = Aes.Decrypt(s2, rk[3]);
|
|
s3 = Aes.Decrypt(s3, rk[3]);
|
|
s4 = Aes.Decrypt(s4, rk[3]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[4]);
|
|
s2 = Aes.Decrypt(s2, rk[4]);
|
|
s3 = Aes.Decrypt(s3, rk[4]);
|
|
s4 = Aes.Decrypt(s4, rk[4]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[5]);
|
|
s2 = Aes.Decrypt(s2, rk[5]);
|
|
s3 = Aes.Decrypt(s3, rk[5]);
|
|
s4 = Aes.Decrypt(s4, rk[5]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[6]);
|
|
s2 = Aes.Decrypt(s2, rk[6]);
|
|
s3 = Aes.Decrypt(s3, rk[6]);
|
|
s4 = Aes.Decrypt(s4, rk[6]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[7]);
|
|
s2 = Aes.Decrypt(s2, rk[7]);
|
|
s3 = Aes.Decrypt(s3, rk[7]);
|
|
s4 = Aes.Decrypt(s4, rk[7]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[8]);
|
|
s2 = Aes.Decrypt(s2, rk[8]);
|
|
s3 = Aes.Decrypt(s3, rk[8]);
|
|
s4 = Aes.Decrypt(s4, rk[8]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[9]);
|
|
s2 = Aes.Decrypt(s2, rk[9]);
|
|
s3 = Aes.Decrypt(s3, rk[9]);
|
|
s4 = Aes.Decrypt(s4, rk[9]);
|
|
|
|
s1 = Aes.DecryptLast(s1, rk[10]);
|
|
s2 = Aes.DecryptLast(s2, rk[10]);
|
|
s3 = Aes.DecryptLast(s3, rk[10]);
|
|
s4 = Aes.DecryptLast(s4, rk[10]);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static void DecryptFour192(Vector128<byte>[] rk,
|
|
ref Vector128<byte> s1, ref Vector128<byte> s2, ref Vector128<byte> s3, ref Vector128<byte> s4)
|
|
{
|
|
s1 = Sse2.Xor(s1, rk[0]);
|
|
s2 = Sse2.Xor(s2, rk[0]);
|
|
s3 = Sse2.Xor(s3, rk[0]);
|
|
s4 = Sse2.Xor(s4, rk[0]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[1]);
|
|
s2 = Aes.Decrypt(s2, rk[1]);
|
|
s3 = Aes.Decrypt(s3, rk[1]);
|
|
s4 = Aes.Decrypt(s4, rk[1]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[2]);
|
|
s2 = Aes.Decrypt(s2, rk[2]);
|
|
s3 = Aes.Decrypt(s3, rk[2]);
|
|
s4 = Aes.Decrypt(s4, rk[2]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[3]);
|
|
s2 = Aes.Decrypt(s2, rk[3]);
|
|
s3 = Aes.Decrypt(s3, rk[3]);
|
|
s4 = Aes.Decrypt(s4, rk[3]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[4]);
|
|
s2 = Aes.Decrypt(s2, rk[4]);
|
|
s3 = Aes.Decrypt(s3, rk[4]);
|
|
s4 = Aes.Decrypt(s4, rk[4]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[5]);
|
|
s2 = Aes.Decrypt(s2, rk[5]);
|
|
s3 = Aes.Decrypt(s3, rk[5]);
|
|
s4 = Aes.Decrypt(s4, rk[5]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[6]);
|
|
s2 = Aes.Decrypt(s2, rk[6]);
|
|
s3 = Aes.Decrypt(s3, rk[6]);
|
|
s4 = Aes.Decrypt(s4, rk[6]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[7]);
|
|
s2 = Aes.Decrypt(s2, rk[7]);
|
|
s3 = Aes.Decrypt(s3, rk[7]);
|
|
s4 = Aes.Decrypt(s4, rk[7]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[8]);
|
|
s2 = Aes.Decrypt(s2, rk[8]);
|
|
s3 = Aes.Decrypt(s3, rk[8]);
|
|
s4 = Aes.Decrypt(s4, rk[8]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[9]);
|
|
s2 = Aes.Decrypt(s2, rk[9]);
|
|
s3 = Aes.Decrypt(s3, rk[9]);
|
|
s4 = Aes.Decrypt(s4, rk[9]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[10]);
|
|
s2 = Aes.Decrypt(s2, rk[10]);
|
|
s3 = Aes.Decrypt(s3, rk[10]);
|
|
s4 = Aes.Decrypt(s4, rk[10]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[11]);
|
|
s2 = Aes.Decrypt(s2, rk[11]);
|
|
s3 = Aes.Decrypt(s3, rk[11]);
|
|
s4 = Aes.Decrypt(s4, rk[11]);
|
|
|
|
s1 = Aes.DecryptLast(s1, rk[12]);
|
|
s2 = Aes.DecryptLast(s2, rk[12]);
|
|
s3 = Aes.DecryptLast(s3, rk[12]);
|
|
s4 = Aes.DecryptLast(s4, rk[12]);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static void DecryptFour256(Vector128<byte>[] rk,
|
|
ref Vector128<byte> s1, ref Vector128<byte> s2, ref Vector128<byte> s3, ref Vector128<byte> s4)
|
|
{
|
|
s1 = Sse2.Xor(s1, rk[0]);
|
|
s2 = Sse2.Xor(s2, rk[0]);
|
|
s3 = Sse2.Xor(s3, rk[0]);
|
|
s4 = Sse2.Xor(s4, rk[0]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[1]);
|
|
s2 = Aes.Decrypt(s2, rk[1]);
|
|
s3 = Aes.Decrypt(s3, rk[1]);
|
|
s4 = Aes.Decrypt(s4, rk[1]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[2]);
|
|
s2 = Aes.Decrypt(s2, rk[2]);
|
|
s3 = Aes.Decrypt(s3, rk[2]);
|
|
s4 = Aes.Decrypt(s4, rk[2]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[3]);
|
|
s2 = Aes.Decrypt(s2, rk[3]);
|
|
s3 = Aes.Decrypt(s3, rk[3]);
|
|
s4 = Aes.Decrypt(s4, rk[3]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[4]);
|
|
s2 = Aes.Decrypt(s2, rk[4]);
|
|
s3 = Aes.Decrypt(s3, rk[4]);
|
|
s4 = Aes.Decrypt(s4, rk[4]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[5]);
|
|
s2 = Aes.Decrypt(s2, rk[5]);
|
|
s3 = Aes.Decrypt(s3, rk[5]);
|
|
s4 = Aes.Decrypt(s4, rk[5]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[6]);
|
|
s2 = Aes.Decrypt(s2, rk[6]);
|
|
s3 = Aes.Decrypt(s3, rk[6]);
|
|
s4 = Aes.Decrypt(s4, rk[6]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[7]);
|
|
s2 = Aes.Decrypt(s2, rk[7]);
|
|
s3 = Aes.Decrypt(s3, rk[7]);
|
|
s4 = Aes.Decrypt(s4, rk[7]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[8]);
|
|
s2 = Aes.Decrypt(s2, rk[8]);
|
|
s3 = Aes.Decrypt(s3, rk[8]);
|
|
s4 = Aes.Decrypt(s4, rk[8]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[9]);
|
|
s2 = Aes.Decrypt(s2, rk[9]);
|
|
s3 = Aes.Decrypt(s3, rk[9]);
|
|
s4 = Aes.Decrypt(s4, rk[9]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[10]);
|
|
s2 = Aes.Decrypt(s2, rk[10]);
|
|
s3 = Aes.Decrypt(s3, rk[10]);
|
|
s4 = Aes.Decrypt(s4, rk[10]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[11]);
|
|
s2 = Aes.Decrypt(s2, rk[11]);
|
|
s3 = Aes.Decrypt(s3, rk[11]);
|
|
s4 = Aes.Decrypt(s4, rk[11]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[12]);
|
|
s2 = Aes.Decrypt(s2, rk[12]);
|
|
s3 = Aes.Decrypt(s3, rk[12]);
|
|
s4 = Aes.Decrypt(s4, rk[12]);
|
|
|
|
s1 = Aes.Decrypt(s1, rk[13]);
|
|
s2 = Aes.Decrypt(s2, rk[13]);
|
|
s3 = Aes.Decrypt(s3, rk[13]);
|
|
s4 = Aes.Decrypt(s4, rk[13]);
|
|
|
|
s1 = Aes.DecryptLast(s1, rk[14]);
|
|
s2 = Aes.DecryptLast(s2, rk[14]);
|
|
s3 = Aes.DecryptLast(s3, rk[14]);
|
|
s4 = Aes.DecryptLast(s4, rk[14]);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static void Encrypt128(Vector128<byte>[] roundKeys, ref Vector128<byte> state)
|
|
{
|
|
state = Sse2.Xor(state, roundKeys[0]);
|
|
state = Aes.Encrypt(state, roundKeys[1]);
|
|
state = Aes.Encrypt(state, roundKeys[2]);
|
|
state = Aes.Encrypt(state, roundKeys[3]);
|
|
state = Aes.Encrypt(state, roundKeys[4]);
|
|
state = Aes.Encrypt(state, roundKeys[5]);
|
|
state = Aes.Encrypt(state, roundKeys[6]);
|
|
state = Aes.Encrypt(state, roundKeys[7]);
|
|
state = Aes.Encrypt(state, roundKeys[8]);
|
|
state = Aes.Encrypt(state, roundKeys[9]);
|
|
state = Aes.EncryptLast(state, roundKeys[10]);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static void Encrypt192(Vector128<byte>[] roundKeys, ref Vector128<byte> state)
|
|
{
|
|
state = Sse2.Xor(state, roundKeys[0]);
|
|
state = Aes.Encrypt(state, roundKeys[1]);
|
|
state = Aes.Encrypt(state, roundKeys[2]);
|
|
state = Aes.Encrypt(state, roundKeys[3]);
|
|
state = Aes.Encrypt(state, roundKeys[4]);
|
|
state = Aes.Encrypt(state, roundKeys[5]);
|
|
state = Aes.Encrypt(state, roundKeys[6]);
|
|
state = Aes.Encrypt(state, roundKeys[7]);
|
|
state = Aes.Encrypt(state, roundKeys[8]);
|
|
state = Aes.Encrypt(state, roundKeys[9]);
|
|
state = Aes.Encrypt(state, roundKeys[10]);
|
|
state = Aes.Encrypt(state, roundKeys[11]);
|
|
state = Aes.EncryptLast(state, roundKeys[12]);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static void Encrypt256(Vector128<byte>[] roundKeys, ref Vector128<byte> state)
|
|
{
|
|
state = Sse2.Xor(state, roundKeys[0]);
|
|
state = Aes.Encrypt(state, roundKeys[1]);
|
|
state = Aes.Encrypt(state, roundKeys[2]);
|
|
state = Aes.Encrypt(state, roundKeys[3]);
|
|
state = Aes.Encrypt(state, roundKeys[4]);
|
|
state = Aes.Encrypt(state, roundKeys[5]);
|
|
state = Aes.Encrypt(state, roundKeys[6]);
|
|
state = Aes.Encrypt(state, roundKeys[7]);
|
|
state = Aes.Encrypt(state, roundKeys[8]);
|
|
state = Aes.Encrypt(state, roundKeys[9]);
|
|
state = Aes.Encrypt(state, roundKeys[10]);
|
|
state = Aes.Encrypt(state, roundKeys[11]);
|
|
state = Aes.Encrypt(state, roundKeys[12]);
|
|
state = Aes.Encrypt(state, roundKeys[13]);
|
|
state = Aes.EncryptLast(state, roundKeys[14]);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static void EncryptFour128(Vector128<byte>[] rk,
|
|
ref Vector128<byte> s1, ref Vector128<byte> s2, ref Vector128<byte> s3, ref Vector128<byte> s4)
|
|
{
|
|
s1 = Sse2.Xor(s1, rk[0]);
|
|
s2 = Sse2.Xor(s2, rk[0]);
|
|
s3 = Sse2.Xor(s3, rk[0]);
|
|
s4 = Sse2.Xor(s4, rk[0]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[1]);
|
|
s2 = Aes.Encrypt(s2, rk[1]);
|
|
s3 = Aes.Encrypt(s3, rk[1]);
|
|
s4 = Aes.Encrypt(s4, rk[1]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[2]);
|
|
s2 = Aes.Encrypt(s2, rk[2]);
|
|
s3 = Aes.Encrypt(s3, rk[2]);
|
|
s4 = Aes.Encrypt(s4, rk[2]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[3]);
|
|
s2 = Aes.Encrypt(s2, rk[3]);
|
|
s3 = Aes.Encrypt(s3, rk[3]);
|
|
s4 = Aes.Encrypt(s4, rk[3]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[4]);
|
|
s2 = Aes.Encrypt(s2, rk[4]);
|
|
s3 = Aes.Encrypt(s3, rk[4]);
|
|
s4 = Aes.Encrypt(s4, rk[4]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[5]);
|
|
s2 = Aes.Encrypt(s2, rk[5]);
|
|
s3 = Aes.Encrypt(s3, rk[5]);
|
|
s4 = Aes.Encrypt(s4, rk[5]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[6]);
|
|
s2 = Aes.Encrypt(s2, rk[6]);
|
|
s3 = Aes.Encrypt(s3, rk[6]);
|
|
s4 = Aes.Encrypt(s4, rk[6]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[7]);
|
|
s2 = Aes.Encrypt(s2, rk[7]);
|
|
s3 = Aes.Encrypt(s3, rk[7]);
|
|
s4 = Aes.Encrypt(s4, rk[7]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[8]);
|
|
s2 = Aes.Encrypt(s2, rk[8]);
|
|
s3 = Aes.Encrypt(s3, rk[8]);
|
|
s4 = Aes.Encrypt(s4, rk[8]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[9]);
|
|
s2 = Aes.Encrypt(s2, rk[9]);
|
|
s3 = Aes.Encrypt(s3, rk[9]);
|
|
s4 = Aes.Encrypt(s4, rk[9]);
|
|
|
|
s1 = Aes.EncryptLast(s1, rk[10]);
|
|
s2 = Aes.EncryptLast(s2, rk[10]);
|
|
s3 = Aes.EncryptLast(s3, rk[10]);
|
|
s4 = Aes.EncryptLast(s4, rk[10]);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static void EncryptFour192(Vector128<byte>[] rk,
|
|
ref Vector128<byte> s1, ref Vector128<byte> s2, ref Vector128<byte> s3, ref Vector128<byte> s4)
|
|
{
|
|
s1 = Sse2.Xor(s1, rk[0]);
|
|
s2 = Sse2.Xor(s2, rk[0]);
|
|
s3 = Sse2.Xor(s3, rk[0]);
|
|
s4 = Sse2.Xor(s4, rk[0]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[1]);
|
|
s2 = Aes.Encrypt(s2, rk[1]);
|
|
s3 = Aes.Encrypt(s3, rk[1]);
|
|
s4 = Aes.Encrypt(s4, rk[1]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[2]);
|
|
s2 = Aes.Encrypt(s2, rk[2]);
|
|
s3 = Aes.Encrypt(s3, rk[2]);
|
|
s4 = Aes.Encrypt(s4, rk[2]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[3]);
|
|
s2 = Aes.Encrypt(s2, rk[3]);
|
|
s3 = Aes.Encrypt(s3, rk[3]);
|
|
s4 = Aes.Encrypt(s4, rk[3]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[4]);
|
|
s2 = Aes.Encrypt(s2, rk[4]);
|
|
s3 = Aes.Encrypt(s3, rk[4]);
|
|
s4 = Aes.Encrypt(s4, rk[4]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[5]);
|
|
s2 = Aes.Encrypt(s2, rk[5]);
|
|
s3 = Aes.Encrypt(s3, rk[5]);
|
|
s4 = Aes.Encrypt(s4, rk[5]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[6]);
|
|
s2 = Aes.Encrypt(s2, rk[6]);
|
|
s3 = Aes.Encrypt(s3, rk[6]);
|
|
s4 = Aes.Encrypt(s4, rk[6]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[7]);
|
|
s2 = Aes.Encrypt(s2, rk[7]);
|
|
s3 = Aes.Encrypt(s3, rk[7]);
|
|
s4 = Aes.Encrypt(s4, rk[7]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[8]);
|
|
s2 = Aes.Encrypt(s2, rk[8]);
|
|
s3 = Aes.Encrypt(s3, rk[8]);
|
|
s4 = Aes.Encrypt(s4, rk[8]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[9]);
|
|
s2 = Aes.Encrypt(s2, rk[9]);
|
|
s3 = Aes.Encrypt(s3, rk[9]);
|
|
s4 = Aes.Encrypt(s4, rk[9]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[10]);
|
|
s2 = Aes.Encrypt(s2, rk[10]);
|
|
s3 = Aes.Encrypt(s3, rk[10]);
|
|
s4 = Aes.Encrypt(s4, rk[10]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[11]);
|
|
s2 = Aes.Encrypt(s2, rk[11]);
|
|
s3 = Aes.Encrypt(s3, rk[11]);
|
|
s4 = Aes.Encrypt(s4, rk[11]);
|
|
|
|
s1 = Aes.EncryptLast(s1, rk[12]);
|
|
s2 = Aes.EncryptLast(s2, rk[12]);
|
|
s3 = Aes.EncryptLast(s3, rk[12]);
|
|
s4 = Aes.EncryptLast(s4, rk[12]);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static void EncryptFour256(Vector128<byte>[] rk,
|
|
ref Vector128<byte> s1, ref Vector128<byte> s2, ref Vector128<byte> s3, ref Vector128<byte> s4)
|
|
{
|
|
s1 = Sse2.Xor(s1, rk[0]);
|
|
s2 = Sse2.Xor(s2, rk[0]);
|
|
s3 = Sse2.Xor(s3, rk[0]);
|
|
s4 = Sse2.Xor(s4, rk[0]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[1]);
|
|
s2 = Aes.Encrypt(s2, rk[1]);
|
|
s3 = Aes.Encrypt(s3, rk[1]);
|
|
s4 = Aes.Encrypt(s4, rk[1]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[2]);
|
|
s2 = Aes.Encrypt(s2, rk[2]);
|
|
s3 = Aes.Encrypt(s3, rk[2]);
|
|
s4 = Aes.Encrypt(s4, rk[2]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[3]);
|
|
s2 = Aes.Encrypt(s2, rk[3]);
|
|
s3 = Aes.Encrypt(s3, rk[3]);
|
|
s4 = Aes.Encrypt(s4, rk[3]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[4]);
|
|
s2 = Aes.Encrypt(s2, rk[4]);
|
|
s3 = Aes.Encrypt(s3, rk[4]);
|
|
s4 = Aes.Encrypt(s4, rk[4]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[5]);
|
|
s2 = Aes.Encrypt(s2, rk[5]);
|
|
s3 = Aes.Encrypt(s3, rk[5]);
|
|
s4 = Aes.Encrypt(s4, rk[5]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[6]);
|
|
s2 = Aes.Encrypt(s2, rk[6]);
|
|
s3 = Aes.Encrypt(s3, rk[6]);
|
|
s4 = Aes.Encrypt(s4, rk[6]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[7]);
|
|
s2 = Aes.Encrypt(s2, rk[7]);
|
|
s3 = Aes.Encrypt(s3, rk[7]);
|
|
s4 = Aes.Encrypt(s4, rk[7]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[8]);
|
|
s2 = Aes.Encrypt(s2, rk[8]);
|
|
s3 = Aes.Encrypt(s3, rk[8]);
|
|
s4 = Aes.Encrypt(s4, rk[8]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[9]);
|
|
s2 = Aes.Encrypt(s2, rk[9]);
|
|
s3 = Aes.Encrypt(s3, rk[9]);
|
|
s4 = Aes.Encrypt(s4, rk[9]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[10]);
|
|
s2 = Aes.Encrypt(s2, rk[10]);
|
|
s3 = Aes.Encrypt(s3, rk[10]);
|
|
s4 = Aes.Encrypt(s4, rk[10]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[11]);
|
|
s2 = Aes.Encrypt(s2, rk[11]);
|
|
s3 = Aes.Encrypt(s3, rk[11]);
|
|
s4 = Aes.Encrypt(s4, rk[11]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[12]);
|
|
s2 = Aes.Encrypt(s2, rk[12]);
|
|
s3 = Aes.Encrypt(s3, rk[12]);
|
|
s4 = Aes.Encrypt(s4, rk[12]);
|
|
|
|
s1 = Aes.Encrypt(s1, rk[13]);
|
|
s2 = Aes.Encrypt(s2, rk[13]);
|
|
s3 = Aes.Encrypt(s3, rk[13]);
|
|
s4 = Aes.Encrypt(s4, rk[13]);
|
|
|
|
s1 = Aes.EncryptLast(s1, rk[14]);
|
|
s2 = Aes.EncryptLast(s2, rk[14]);
|
|
s3 = Aes.EncryptLast(s3, rk[14]);
|
|
s4 = Aes.EncryptLast(s4, rk[14]);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
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 MemoryMarshal.Read<Vector128<byte>>(t);
|
|
|
|
return Vector128.Create(
|
|
BinaryPrimitives.ReadUInt64LittleEndian(t[..8]),
|
|
BinaryPrimitives.ReadUInt64LittleEndian(t[8..])
|
|
).AsByte();
|
|
#endif
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
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 MemoryMarshal.Read<Vector64<byte>>(t);
|
|
|
|
return Vector64.Create(
|
|
BinaryPrimitives.ReadUInt64LittleEndian(t[..8])
|
|
).AsByte();
|
|
#endif
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
private static void Store128(Vector128<byte> s, Span<byte> t)
|
|
{
|
|
#if NET7_0_OR_GREATER
|
|
Vector128.CopyTo(s, t);
|
|
#else
|
|
if (BitConverter.IsLittleEndian && Unsafe.SizeOf<Vector128<byte>>() == 16)
|
|
{
|
|
MemoryMarshal.Write(t, ref s);
|
|
return;
|
|
}
|
|
|
|
var u = s.AsUInt64();
|
|
BinaryPrimitives.WriteUInt64LittleEndian(t[..8], u.GetElement(0));
|
|
BinaryPrimitives.WriteUInt64LittleEndian(t[8..], u.GetElement(1));
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
#pragma warning restore
|
|
#endif
|