mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Avoid allocations when doing encryption with AES-NI
This commit is contained in:
parent
df646fb503
commit
2752a7c3db
16 changed files with 302 additions and 111 deletions
|
@ -1,6 +1,9 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
#if NETCOREAPP
|
||||
using System.Runtime.InteropServices;
|
||||
#endif
|
||||
|
||||
namespace LibHac.Common
|
||||
{
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
using System;
|
||||
// ReSharper disable AssignmentIsFullyDiscarded
|
||||
using System;
|
||||
|
||||
#if HAS_INTRINSICS
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
using LibHac.Crypto2.Detail;
|
||||
#endif
|
||||
|
||||
namespace LibHac.Crypto2
|
||||
|
@ -25,7 +27,7 @@ namespace LibHac.Crypto2
|
|||
#if HAS_INTRINSICS
|
||||
if (IsAesNiSupported() && !preferDotNetCrypto)
|
||||
{
|
||||
return new AesEcbDecryptorHw(key);
|
||||
return new AesEcbDecryptorNi(key);
|
||||
}
|
||||
#endif
|
||||
return new AesEcbDecryptor(key);
|
||||
|
@ -36,7 +38,7 @@ namespace LibHac.Crypto2
|
|||
#if HAS_INTRINSICS
|
||||
if (IsAesNiSupported() && !preferDotNetCrypto)
|
||||
{
|
||||
return new AesEcbEncryptorHw(key);
|
||||
return new AesEcbEncryptorNi(key);
|
||||
}
|
||||
#endif
|
||||
return new AesEcbEncryptor(key);
|
||||
|
@ -47,7 +49,7 @@ namespace LibHac.Crypto2
|
|||
#if HAS_INTRINSICS
|
||||
if (IsAesNiSupported() && !preferDotNetCrypto)
|
||||
{
|
||||
return new AesCbcDecryptorHw(key, iv);
|
||||
return new AesCbcDecryptorNi(key, iv);
|
||||
}
|
||||
#endif
|
||||
return new AesCbcDecryptor(key, iv);
|
||||
|
@ -58,7 +60,7 @@ namespace LibHac.Crypto2
|
|||
#if HAS_INTRINSICS
|
||||
if (IsAesNiSupported() && !preferDotNetCrypto)
|
||||
{
|
||||
return new AesCbcEncryptorHw(key, iv);
|
||||
return new AesCbcEncryptorNi(key, iv);
|
||||
}
|
||||
#endif
|
||||
return new AesCbcEncryptor(key, iv);
|
||||
|
@ -66,6 +68,12 @@ namespace LibHac.Crypto2
|
|||
|
||||
public static ICipher CreateCtrDecryptor(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv, bool preferDotNetCrypto = false)
|
||||
{
|
||||
#if HAS_INTRINSICS
|
||||
if (IsAesNiSupported() && !preferDotNetCrypto)
|
||||
{
|
||||
return new AesCtrCipherNi(key, iv);
|
||||
}
|
||||
#endif
|
||||
// Encryption and decryption in counter mode is the same operation
|
||||
return CreateCtrEncryptor(key, iv, preferDotNetCrypto);
|
||||
}
|
||||
|
@ -75,7 +83,7 @@ namespace LibHac.Crypto2
|
|||
#if HAS_INTRINSICS
|
||||
if (IsAesNiSupported() && !preferDotNetCrypto)
|
||||
{
|
||||
return new AesCtrEncryptorHw(key, iv);
|
||||
return new AesCtrCipherNi(key, iv);
|
||||
}
|
||||
#endif
|
||||
return new AesCtrEncryptor(key, iv);
|
||||
|
@ -87,7 +95,7 @@ namespace LibHac.Crypto2
|
|||
#if HAS_INTRINSICS
|
||||
if (IsAesNiSupported() && !preferDotNetCrypto)
|
||||
{
|
||||
return new AesXtsCipherHw(key1, key2, iv, true);
|
||||
return new AesXtsDecryptorNi(key1, key2, iv);
|
||||
}
|
||||
#endif
|
||||
return new AesXtsCipher(key1, key2, iv, true);
|
||||
|
@ -99,7 +107,7 @@ namespace LibHac.Crypto2
|
|||
#if HAS_INTRINSICS
|
||||
if (IsAesNiSupported() && !preferDotNetCrypto)
|
||||
{
|
||||
return new AesXtsCipherHw(key1, key2, iv, false);
|
||||
return new AesXtsEncryptorNi(key1, key2, iv);
|
||||
}
|
||||
#endif
|
||||
return new AesXtsCipher(key1, key2, iv, false);
|
||||
|
@ -108,6 +116,17 @@ namespace LibHac.Crypto2
|
|||
public static void EncryptEcb128(ReadOnlySpan<byte> input, Span<byte> output, ReadOnlySpan<byte> key,
|
||||
bool preferDotNetCrypto = false)
|
||||
{
|
||||
#if HAS_INTRINSICS
|
||||
if (IsAesNiSupported() && !preferDotNetCrypto)
|
||||
{
|
||||
AesEcbModeNi cipherNi;
|
||||
unsafe { _ = &cipherNi; } // workaround for CS0165
|
||||
|
||||
cipherNi.Initialize(key, false);
|
||||
cipherNi.Encrypt(input, output);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ICipher cipher = CreateEcbEncryptor(key, preferDotNetCrypto);
|
||||
|
||||
cipher.Transform(input, output);
|
||||
|
@ -116,6 +135,17 @@ namespace LibHac.Crypto2
|
|||
public static void DecryptEcb128(ReadOnlySpan<byte> input, Span<byte> output, ReadOnlySpan<byte> key,
|
||||
bool preferDotNetCrypto = false)
|
||||
{
|
||||
#if HAS_INTRINSICS
|
||||
if (IsAesNiSupported() && !preferDotNetCrypto)
|
||||
{
|
||||
AesEcbModeNi cipherNi;
|
||||
unsafe { _ = &cipherNi; } // workaround for CS0165
|
||||
|
||||
cipherNi.Initialize(key, true);
|
||||
cipherNi.Decrypt(input, output);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ICipher cipher = CreateEcbDecryptor(key, preferDotNetCrypto);
|
||||
|
||||
cipher.Transform(input, output);
|
||||
|
@ -124,6 +154,17 @@ namespace LibHac.Crypto2
|
|||
public static void EncryptCbc128(ReadOnlySpan<byte> input, Span<byte> output, ReadOnlySpan<byte> key,
|
||||
ReadOnlySpan<byte> iv, bool preferDotNetCrypto = false)
|
||||
{
|
||||
#if HAS_INTRINSICS
|
||||
if (IsAesNiSupported() && !preferDotNetCrypto)
|
||||
{
|
||||
AesCbcModeNi cipherNi;
|
||||
unsafe { _ = &cipherNi; } // workaround for CS0165
|
||||
|
||||
cipherNi.Initialize(key, iv, false);
|
||||
cipherNi.Encrypt(input, output);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ICipher cipher = CreateCbcEncryptor(key, iv, preferDotNetCrypto);
|
||||
|
||||
cipher.Transform(input, output);
|
||||
|
@ -132,6 +173,17 @@ namespace LibHac.Crypto2
|
|||
public static void DecryptCbc128(ReadOnlySpan<byte> input, Span<byte> output, ReadOnlySpan<byte> key,
|
||||
ReadOnlySpan<byte> iv, bool preferDotNetCrypto = false)
|
||||
{
|
||||
#if HAS_INTRINSICS
|
||||
if (IsAesNiSupported() && !preferDotNetCrypto)
|
||||
{
|
||||
AesCbcModeNi cipherNi;
|
||||
unsafe { _ = &cipherNi; } // workaround for CS0165
|
||||
|
||||
cipherNi.Initialize(key, iv, true);
|
||||
cipherNi.Decrypt(input, output);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ICipher cipher = CreateCbcDecryptor(key, iv, preferDotNetCrypto);
|
||||
|
||||
cipher.Transform(input, output);
|
||||
|
@ -140,6 +192,17 @@ namespace LibHac.Crypto2
|
|||
public static void EncryptCtr128(ReadOnlySpan<byte> input, Span<byte> output, ReadOnlySpan<byte> key,
|
||||
ReadOnlySpan<byte> iv, bool preferDotNetCrypto = false)
|
||||
{
|
||||
#if HAS_INTRINSICS
|
||||
if (IsAesNiSupported() && !preferDotNetCrypto)
|
||||
{
|
||||
AesCtrModeNi cipherNi;
|
||||
unsafe { _ = &cipherNi; } // workaround for CS0165
|
||||
|
||||
cipherNi.Initialize(key, iv);
|
||||
cipherNi.Transform(input, output);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ICipher cipher = CreateCtrEncryptor(key, iv, preferDotNetCrypto);
|
||||
|
||||
cipher.Transform(input, output);
|
||||
|
@ -148,6 +211,17 @@ namespace LibHac.Crypto2
|
|||
public static void DecryptCtr128(ReadOnlySpan<byte> input, Span<byte> output, ReadOnlySpan<byte> key,
|
||||
ReadOnlySpan<byte> iv, bool preferDotNetCrypto = false)
|
||||
{
|
||||
#if HAS_INTRINSICS
|
||||
if (IsAesNiSupported() && !preferDotNetCrypto)
|
||||
{
|
||||
AesCtrModeNi cipherNi;
|
||||
unsafe { _ = &cipherNi; } // workaround for CS0165
|
||||
|
||||
cipherNi.Initialize(key, iv);
|
||||
cipherNi.Transform(input, output);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ICipher cipher = CreateCtrDecryptor(key, iv, preferDotNetCrypto);
|
||||
|
||||
cipher.Transform(input, output);
|
||||
|
@ -156,6 +230,17 @@ namespace LibHac.Crypto2
|
|||
public static void EncryptXts128(ReadOnlySpan<byte> input, Span<byte> output, ReadOnlySpan<byte> key1,
|
||||
ReadOnlySpan<byte> key2, ReadOnlySpan<byte> iv, bool preferDotNetCrypto = false)
|
||||
{
|
||||
#if HAS_INTRINSICS
|
||||
if (IsAesNiSupported() && !preferDotNetCrypto)
|
||||
{
|
||||
AesXtsModeNi cipherNi;
|
||||
unsafe { _ = &cipherNi; } // workaround for CS0165
|
||||
|
||||
cipherNi.Initialize(key1, key2, iv, false);
|
||||
cipherNi.Encrypt(input, output);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ICipher cipher = CreateXtsEncryptor(key1, key2, iv, preferDotNetCrypto);
|
||||
|
||||
cipher.Transform(input, output);
|
||||
|
@ -164,6 +249,17 @@ namespace LibHac.Crypto2
|
|||
public static void DecryptXts128(ReadOnlySpan<byte> input, Span<byte> output, ReadOnlySpan<byte> key1,
|
||||
ReadOnlySpan<byte> key2, ReadOnlySpan<byte> iv, bool preferDotNetCrypto = false)
|
||||
{
|
||||
#if HAS_INTRINSICS
|
||||
if (IsAesNiSupported() && !preferDotNetCrypto)
|
||||
{
|
||||
AesXtsModeNi cipherNi;
|
||||
unsafe { _ = &cipherNi; } // workaround for CS0165
|
||||
|
||||
cipherNi.Initialize(key1, key2, iv, true);
|
||||
cipherNi.Decrypt(input, output);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ICipher cipher = CreateXtsDecryptor(key1, key2, iv, preferDotNetCrypto);
|
||||
|
||||
cipher.Transform(input, output);
|
||||
|
|
39
src/LibHac/Crypto2/AesCbcCipherNi.cs
Normal file
39
src/LibHac/Crypto2/AesCbcCipherNi.cs
Normal file
|
@ -0,0 +1,39 @@
|
|||
#if HAS_INTRINSICS
|
||||
using System;
|
||||
using LibHac.Crypto2.Detail;
|
||||
|
||||
namespace LibHac.Crypto2
|
||||
{
|
||||
public struct AesCbcEncryptorNi : ICipher
|
||||
{
|
||||
private AesCbcModeNi _baseCipher;
|
||||
|
||||
public AesCbcEncryptorNi(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv)
|
||||
{
|
||||
_baseCipher = new AesCbcModeNi();
|
||||
_baseCipher.Initialize(key, iv, false);
|
||||
}
|
||||
|
||||
public void Transform(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
_baseCipher.Encrypt(input, output);
|
||||
}
|
||||
}
|
||||
|
||||
public struct AesCbcDecryptorNi : ICipher
|
||||
{
|
||||
private AesCbcModeNi _baseCipher;
|
||||
|
||||
public AesCbcDecryptorNi(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv)
|
||||
{
|
||||
_baseCipher = new AesCbcModeNi();
|
||||
_baseCipher.Initialize(key, iv, true);
|
||||
}
|
||||
|
||||
public void Transform(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
_baseCipher.Decrypt(input, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
23
src/LibHac/Crypto2/AesCtrCipherNi.cs
Normal file
23
src/LibHac/Crypto2/AesCtrCipherNi.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
#if HAS_INTRINSICS
|
||||
using System;
|
||||
using LibHac.Crypto2.Detail;
|
||||
|
||||
namespace LibHac.Crypto2
|
||||
{
|
||||
public class AesCtrCipherNi : ICipher
|
||||
{
|
||||
private AesCtrModeNi _baseCipher;
|
||||
|
||||
public AesCtrCipherNi(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv)
|
||||
{
|
||||
_baseCipher = new AesCtrModeNi();
|
||||
_baseCipher.Initialize(key, iv);
|
||||
}
|
||||
|
||||
public void Transform(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
_baseCipher.Transform(input, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
39
src/LibHac/Crypto2/AesEcbCipherNi.cs
Normal file
39
src/LibHac/Crypto2/AesEcbCipherNi.cs
Normal file
|
@ -0,0 +1,39 @@
|
|||
#if HAS_INTRINSICS
|
||||
using System;
|
||||
using LibHac.Crypto2.Detail;
|
||||
|
||||
namespace LibHac.Crypto2
|
||||
{
|
||||
public class AesEcbEncryptorNi : ICipher
|
||||
{
|
||||
private AesEcbModeNi _baseCipher;
|
||||
|
||||
public AesEcbEncryptorNi(ReadOnlySpan<byte> key)
|
||||
{
|
||||
_baseCipher = new AesEcbModeNi();
|
||||
_baseCipher.Initialize(key, false);
|
||||
}
|
||||
|
||||
public void Transform(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
_baseCipher.Encrypt(input, output);
|
||||
}
|
||||
}
|
||||
|
||||
public class AesEcbDecryptorNi : ICipher
|
||||
{
|
||||
private AesEcbModeNi _baseCipher;
|
||||
|
||||
public AesEcbDecryptorNi(ReadOnlySpan<byte> key)
|
||||
{
|
||||
_baseCipher = new AesEcbModeNi();
|
||||
_baseCipher.Initialize(key, true);
|
||||
}
|
||||
|
||||
public void Transform(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
_baseCipher.Decrypt(input, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,38 +0,0 @@
|
|||
#if HAS_INTRINSICS
|
||||
using System;
|
||||
|
||||
namespace LibHac.Crypto2
|
||||
{
|
||||
public class AesEcbEncryptorHw : ICipher
|
||||
{
|
||||
private AesCoreNi _aesCore;
|
||||
|
||||
public AesEcbEncryptorHw(ReadOnlySpan<byte> key)
|
||||
{
|
||||
_aesCore = new AesCoreNi();
|
||||
_aesCore.Initialize(key, false);
|
||||
}
|
||||
|
||||
public void Transform(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
_aesCore.Encrypt(input, output);
|
||||
}
|
||||
}
|
||||
|
||||
public class AesEcbDecryptorHw : ICipher
|
||||
{
|
||||
private AesCoreNi _aesCore;
|
||||
|
||||
public AesEcbDecryptorHw(ReadOnlySpan<byte> key)
|
||||
{
|
||||
_aesCore = new AesCoreNi();
|
||||
_aesCore.Initialize(key, true);
|
||||
}
|
||||
|
||||
public void Transform(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
_aesCore.Decrypt(input, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
39
src/LibHac/Crypto2/AesXtsCipherNi.cs
Normal file
39
src/LibHac/Crypto2/AesXtsCipherNi.cs
Normal file
|
@ -0,0 +1,39 @@
|
|||
#if HAS_INTRINSICS
|
||||
using System;
|
||||
using LibHac.Crypto2.Detail;
|
||||
|
||||
namespace LibHac.Crypto2
|
||||
{
|
||||
public class AesXtsEncryptorNi : ICipher
|
||||
{
|
||||
private AesXtsModeNi _baseCipher;
|
||||
|
||||
public AesXtsEncryptorNi(ReadOnlySpan<byte> key1, ReadOnlySpan<byte> key2, ReadOnlySpan<byte> iv)
|
||||
{
|
||||
_baseCipher = new AesXtsModeNi();
|
||||
_baseCipher.Initialize(key1, key2, iv, false);
|
||||
}
|
||||
|
||||
public void Transform(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
_baseCipher.Encrypt(input, output);
|
||||
}
|
||||
}
|
||||
|
||||
public class AesXtsDecryptorNi : ICipher
|
||||
{
|
||||
private AesXtsModeNi _baseCipher;
|
||||
|
||||
public AesXtsDecryptorNi(ReadOnlySpan<byte> key1, ReadOnlySpan<byte> key2, ReadOnlySpan<byte> iv)
|
||||
{
|
||||
_baseCipher = new AesXtsModeNi();
|
||||
_baseCipher.Initialize(key1, key2, iv, true);
|
||||
}
|
||||
|
||||
public void Transform(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
_baseCipher.Decrypt(input, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,28 +1,28 @@
|
|||
#if HAS_INTRINSICS
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
|
||||
namespace LibHac.Crypto2
|
||||
namespace LibHac.Crypto2.Detail
|
||||
{
|
||||
public struct AesCbcEncryptorHw : ICipher
|
||||
public struct AesCbcModeNi
|
||||
{
|
||||
#pragma warning disable 649
|
||||
private AesCoreNi _aesCore;
|
||||
#pragma warning restore 649
|
||||
|
||||
private Vector128<byte> _iv;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||
public AesCbcEncryptorHw(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv)
|
||||
public void Initialize(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv, bool isDecrypting)
|
||||
{
|
||||
_aesCore = new AesCoreNi();
|
||||
_aesCore.Initialize(key, false);
|
||||
_aesCore.Initialize(key, isDecrypting);
|
||||
|
||||
_iv = Unsafe.ReadUnaligned<Vector128<byte>>(ref MemoryMarshal.GetReference(iv));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||
public void Transform(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
public void Encrypt(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
int blockCount = Math.Min(input.Length, output.Length) >> 4;
|
||||
|
||||
|
@ -43,24 +43,8 @@ namespace LibHac.Crypto2
|
|||
|
||||
_iv = iv;
|
||||
}
|
||||
}
|
||||
|
||||
public struct AesCbcDecryptorHw : ICipher
|
||||
{
|
||||
private AesCoreNi _aesCore;
|
||||
private Vector128<byte> _iv;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||
public AesCbcDecryptorHw(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv)
|
||||
{
|
||||
_aesCore = new AesCoreNi();
|
||||
_aesCore.Initialize(key, true);
|
||||
|
||||
_iv = Unsafe.ReadUnaligned<Vector128<byte>>(ref MemoryMarshal.GetReference(iv));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||
public void Transform(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
public void Decrypt(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
int blockCount = Math.Min(input.Length, output.Length) >> 4;
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
#if NETCOREAPP
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace LibHac.Crypto2
|
||||
namespace LibHac.Crypto2.Detail
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Size = RoundKeyCount * RoundKeySize)]
|
||||
public struct AesCoreNi
|
||||
|
@ -15,13 +15,6 @@ namespace LibHac.Crypto2
|
|||
|
||||
private Vector128<byte> _roundKeys;
|
||||
|
||||
public AesCoreNi(ReadOnlySpan<byte> key, bool isDecrypting)
|
||||
{
|
||||
_roundKeys = default;
|
||||
|
||||
KeyExpansion(key, MemoryMarshal.CreateSpan(ref _roundKeys, RoundKeyCount), isDecrypting);
|
||||
}
|
||||
|
||||
public void Initialize(ReadOnlySpan<byte> key, bool isDecrypting)
|
||||
{
|
||||
KeyExpansion(key, MemoryMarshal.CreateSpan(ref _roundKeys, RoundKeyCount), isDecrypting);
|
||||
|
@ -30,7 +23,6 @@ namespace LibHac.Crypto2
|
|||
public readonly ReadOnlySpan<Vector128<byte>> RoundKeys =>
|
||||
MemoryMarshal.CreateReadOnlySpan(ref Unsafe.AsRef(in _roundKeys), RoundKeyCount);
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||
public readonly void Encrypt(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
|
@ -5,17 +5,18 @@ using System.Runtime.InteropServices;
|
|||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
|
||||
namespace LibHac.Crypto2
|
||||
namespace LibHac.Crypto2.Detail
|
||||
{
|
||||
public class AesCtrEncryptorHw : ICipher
|
||||
public struct AesCtrModeNi
|
||||
{
|
||||
#pragma warning disable 649
|
||||
private AesCoreNi _aesCore;
|
||||
#pragma warning restore 649
|
||||
|
||||
private Vector128<byte> _iv;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||
public AesCtrEncryptorHw(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv)
|
||||
public void Initialize(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv)
|
||||
{
|
||||
_aesCore = new AesCoreNi();
|
||||
_aesCore.Initialize(key, false);
|
||||
|
||||
_iv = Unsafe.ReadUnaligned<Vector128<byte>>(ref MemoryMarshal.GetReference(iv));
|
28
src/LibHac/Crypto2/Detail/AesEcbModeNi.cs
Normal file
28
src/LibHac/Crypto2/Detail/AesEcbModeNi.cs
Normal file
|
@ -0,0 +1,28 @@
|
|||
#if HAS_INTRINSICS
|
||||
using System;
|
||||
|
||||
namespace LibHac.Crypto2.Detail
|
||||
{
|
||||
public struct AesEcbModeNi
|
||||
{
|
||||
#pragma warning disable 649
|
||||
private AesCoreNi _aesCore;
|
||||
#pragma warning restore 649
|
||||
|
||||
public void Initialize(ReadOnlySpan<byte> key, bool isDecrypting)
|
||||
{
|
||||
_aesCore.Initialize(key, isDecrypting);
|
||||
}
|
||||
|
||||
public void Encrypt(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
_aesCore.Encrypt(input, output);
|
||||
}
|
||||
|
||||
public void Decrypt(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
_aesCore.Decrypt(input, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -7,30 +7,27 @@ using System.Runtime.Intrinsics;
|
|||
using System.Runtime.Intrinsics.X86;
|
||||
using LibHac.Common;
|
||||
|
||||
namespace LibHac.Crypto2
|
||||
namespace LibHac.Crypto2.Detail
|
||||
{
|
||||
public class AesXtsCipherHw : ICipher
|
||||
public struct AesXtsModeNi
|
||||
{
|
||||
#pragma warning disable 649
|
||||
private AesCoreNi _dataAesCore;
|
||||
private AesCoreNi _tweakAesCore;
|
||||
private Vector128<byte> _iv;
|
||||
private bool _decrypting;
|
||||
#pragma warning restore 649
|
||||
|
||||
public AesXtsCipherHw(ReadOnlySpan<byte> key1, ReadOnlySpan<byte> key2, ReadOnlySpan<byte> iv, bool decrypting)
|
||||
private Vector128<byte> _iv;
|
||||
|
||||
public void Initialize(ReadOnlySpan<byte> key1, ReadOnlySpan<byte> key2, ReadOnlySpan<byte> iv, bool decrypting)
|
||||
{
|
||||
Debug.Assert(key1.Length == AesCrypto.KeySize128);
|
||||
Debug.Assert(key2.Length == AesCrypto.KeySize128);
|
||||
Debug.Assert(iv.Length == AesCrypto.KeySize128);
|
||||
|
||||
_dataAesCore = new AesCoreNi();
|
||||
_dataAesCore.Initialize(key1, decrypting);
|
||||
|
||||
_tweakAesCore = new AesCoreNi();
|
||||
_tweakAesCore.Initialize(key2, false);
|
||||
|
||||
_iv = Unsafe.ReadUnaligned<Vector128<byte>>(ref MemoryMarshal.GetReference(iv));
|
||||
|
||||
_decrypting = decrypting;
|
||||
}
|
||||
|
||||
public void Encrypt(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
|
@ -158,18 +155,6 @@ namespace LibHac.Crypto2
|
|||
prevOutBlock = Sse2.Xor(tmp, tweak);
|
||||
}
|
||||
|
||||
public void Transform(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
if (_decrypting)
|
||||
{
|
||||
Decrypt(input, output);
|
||||
}
|
||||
else
|
||||
{
|
||||
Encrypt(input, output);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vector128<byte> Gf128Mul(Vector128<byte> iv, Vector128<byte> mask)
|
||||
{
|
Loading…
Reference in a new issue