diff --git a/src/LibHac/Crypto/Aes.cs b/src/LibHac/Crypto/Aes.cs index 52df2d8e..f24cb4ef 100644 --- a/src/LibHac/Crypto/Aes.cs +++ b/src/LibHac/Crypto/Aes.cs @@ -67,7 +67,7 @@ namespace LibHac.Crypto return new AesCbcEncryptor(key, iv); } - public static ICipher CreateCtrDecryptor(ReadOnlySpan key, ReadOnlySpan iv, bool preferDotNetCrypto = false) + public static ICipherWithIv CreateCtrDecryptor(ReadOnlySpan key, ReadOnlySpan iv, bool preferDotNetCrypto = false) { #if HAS_INTRINSICS if (IsAesNiSupported() && !preferDotNetCrypto) @@ -79,7 +79,7 @@ namespace LibHac.Crypto return CreateCtrEncryptor(key, iv, preferDotNetCrypto); } - public static ICipher CreateCtrEncryptor(ReadOnlySpan key, ReadOnlySpan iv, bool preferDotNetCrypto = false) + public static ICipherWithIv CreateCtrEncryptor(ReadOnlySpan key, ReadOnlySpan iv, bool preferDotNetCrypto = false) { #if HAS_INTRINSICS if (IsAesNiSupported() && !preferDotNetCrypto) @@ -90,7 +90,7 @@ namespace LibHac.Crypto return new AesCtrCipher(key, iv); } - public static ICipher CreateXtsDecryptor(ReadOnlySpan key1, ReadOnlySpan key2, + public static ICipherWithIv CreateXtsDecryptor(ReadOnlySpan key1, ReadOnlySpan key2, ReadOnlySpan iv, bool preferDotNetCrypto = false) { #if HAS_INTRINSICS @@ -102,7 +102,7 @@ namespace LibHac.Crypto return new AesXtsDecryptor(key1, key2, iv); } - public static ICipher CreateXtsEncryptor(ReadOnlySpan key1, ReadOnlySpan key2, + public static ICipherWithIv CreateXtsEncryptor(ReadOnlySpan key1, ReadOnlySpan key2, ReadOnlySpan iv, bool preferDotNetCrypto = false) { #if HAS_INTRINSICS diff --git a/src/LibHac/Crypto/AesCbcCipherNi.cs b/src/LibHac/Crypto/AesCbcCipherNi.cs index 618549e8..2b2b3ab4 100644 --- a/src/LibHac/Crypto/AesCbcCipherNi.cs +++ b/src/LibHac/Crypto/AesCbcCipherNi.cs @@ -1,13 +1,18 @@ #if HAS_INTRINSICS using System; +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; +using LibHac.Common; using LibHac.Crypto.Detail; namespace LibHac.Crypto { - public struct AesCbcEncryptorNi : ICipher + public class AesCbcEncryptorNi : ICipherWithIv { private AesCbcModeNi _baseCipher; + public ref Buffer16 Iv => ref Unsafe.As, Buffer16>(ref _baseCipher.Iv); + public AesCbcEncryptorNi(ReadOnlySpan key, ReadOnlySpan iv) { _baseCipher = new AesCbcModeNi(); @@ -20,10 +25,12 @@ namespace LibHac.Crypto } } - public struct AesCbcDecryptorNi : ICipher + public class AesCbcDecryptorNi : ICipherWithIv { private AesCbcModeNi _baseCipher; + public ref Buffer16 Iv => ref Unsafe.As, Buffer16>(ref _baseCipher.Iv); + public AesCbcDecryptorNi(ReadOnlySpan key, ReadOnlySpan iv) { _baseCipher = new AesCbcModeNi(); diff --git a/src/LibHac/Crypto/AesCtrCipher.cs b/src/LibHac/Crypto/AesCtrCipher.cs index 4057c113..d8f1e6d7 100644 --- a/src/LibHac/Crypto/AesCtrCipher.cs +++ b/src/LibHac/Crypto/AesCtrCipher.cs @@ -1,12 +1,15 @@ using System; +using LibHac.Common; using LibHac.Crypto.Detail; namespace LibHac.Crypto { - public class AesCtrCipher : ICipher + public class AesCtrCipher : ICipherWithIv { private AesCtrMode _baseCipher; + public ref Buffer16 Iv => ref _baseCipher.Iv; + public AesCtrCipher(ReadOnlySpan key, ReadOnlySpan iv) { _baseCipher = new AesCtrMode(); diff --git a/src/LibHac/Crypto/AesCtrCipherNi.cs b/src/LibHac/Crypto/AesCtrCipherNi.cs index ba177ca6..13e71486 100644 --- a/src/LibHac/Crypto/AesCtrCipherNi.cs +++ b/src/LibHac/Crypto/AesCtrCipherNi.cs @@ -1,13 +1,18 @@ #if HAS_INTRINSICS using System; +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; +using LibHac.Common; using LibHac.Crypto.Detail; namespace LibHac.Crypto { - public class AesCtrCipherNi : ICipher + public class AesCtrCipherNi : ICipherWithIv { private AesCtrModeNi _baseCipher; + public ref Buffer16 Iv => ref Unsafe.As, Buffer16>(ref _baseCipher.Iv); + public AesCtrCipherNi(ReadOnlySpan key, ReadOnlySpan iv) { _baseCipher = new AesCtrModeNi(); diff --git a/src/LibHac/Crypto/AesXtsCipher.cs b/src/LibHac/Crypto/AesXtsCipher.cs index 152e3d5b..86a07c83 100644 --- a/src/LibHac/Crypto/AesXtsCipher.cs +++ b/src/LibHac/Crypto/AesXtsCipher.cs @@ -1,12 +1,15 @@ using System; +using LibHac.Common; using LibHac.Crypto.Detail; namespace LibHac.Crypto { - public class AesXtsEncryptor : ICipher + public class AesXtsEncryptor : ICipherWithIv { private AesXtsMode _baseCipher; + public ref Buffer16 Iv => ref _baseCipher.Iv; + public AesXtsEncryptor(ReadOnlySpan key1, ReadOnlySpan key2, ReadOnlySpan iv) { _baseCipher = new AesXtsMode(); @@ -19,9 +22,11 @@ namespace LibHac.Crypto } } - public class AesXtsDecryptor : ICipher + public class AesXtsDecryptor : ICipherWithIv { private AesXtsMode _baseCipher; + + public ref Buffer16 Iv => ref _baseCipher.Iv; public AesXtsDecryptor(ReadOnlySpan key1, ReadOnlySpan key2, ReadOnlySpan iv) { diff --git a/src/LibHac/Crypto/AesXtsCipherNi.cs b/src/LibHac/Crypto/AesXtsCipherNi.cs index a4b13730..d310bfe0 100644 --- a/src/LibHac/Crypto/AesXtsCipherNi.cs +++ b/src/LibHac/Crypto/AesXtsCipherNi.cs @@ -1,13 +1,18 @@ #if HAS_INTRINSICS using System; +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; +using LibHac.Common; using LibHac.Crypto.Detail; namespace LibHac.Crypto { - public class AesXtsEncryptorNi : ICipher + public class AesXtsEncryptorNi : ICipherWithIv { private AesXtsModeNi _baseCipher; + public ref Buffer16 Iv => ref Unsafe.As, Buffer16>(ref _baseCipher.Iv); + public AesXtsEncryptorNi(ReadOnlySpan key1, ReadOnlySpan key2, ReadOnlySpan iv) { _baseCipher = new AesXtsModeNi(); @@ -20,10 +25,12 @@ namespace LibHac.Crypto } } - public class AesXtsDecryptorNi : ICipher + public class AesXtsDecryptorNi : ICipherWithIv { private AesXtsModeNi _baseCipher; + public ref Buffer16 Iv => ref Unsafe.As, Buffer16>(ref _baseCipher.Iv); + public AesXtsDecryptorNi(ReadOnlySpan key1, ReadOnlySpan key2, ReadOnlySpan iv) { _baseCipher = new AesXtsModeNi(); diff --git a/src/LibHac/Crypto/Detail/AesCbcModeNi.cs b/src/LibHac/Crypto/Detail/AesCbcModeNi.cs index e57499b2..4ee79f7f 100644 --- a/src/LibHac/Crypto/Detail/AesCbcModeNi.cs +++ b/src/LibHac/Crypto/Detail/AesCbcModeNi.cs @@ -14,7 +14,7 @@ namespace LibHac.Crypto.Detail private AesCoreNi _aesCore; #pragma warning restore 649 - private Vector128 _iv; + public Vector128 Iv; public void Initialize(ReadOnlySpan key, ReadOnlySpan iv, bool isDecrypting) { @@ -22,7 +22,7 @@ namespace LibHac.Crypto.Detail _aesCore.Initialize(key, isDecrypting); - _iv = Unsafe.ReadUnaligned>(ref MemoryMarshal.GetReference(iv)); + Iv = Unsafe.ReadUnaligned>(ref MemoryMarshal.GetReference(iv)); } public void Encrypt(ReadOnlySpan input, Span output) @@ -32,7 +32,7 @@ namespace LibHac.Crypto.Detail ref Vector128 inBlock = ref Unsafe.As>(ref MemoryMarshal.GetReference(input)); ref Vector128 outBlock = ref Unsafe.As>(ref MemoryMarshal.GetReference(output)); - Vector128 iv = _iv; + Vector128 iv = Iv; for (int i = 0; i < blockCount; i++) { @@ -44,7 +44,7 @@ namespace LibHac.Crypto.Detail outBlock = ref Unsafe.Add(ref outBlock, 1); } - _iv = iv; + Iv = iv; } public void Decrypt(ReadOnlySpan input, Span output) @@ -54,7 +54,7 @@ namespace LibHac.Crypto.Detail ref Vector128 inBlock = ref Unsafe.As>(ref MemoryMarshal.GetReference(input)); ref Vector128 outBlock = ref Unsafe.As>(ref MemoryMarshal.GetReference(output)); - Vector128 iv = _iv; + Vector128 iv = Iv; while (remainingBlocks > 7) { @@ -106,7 +106,7 @@ namespace LibHac.Crypto.Detail remainingBlocks -= 1; } - _iv = iv; + Iv = iv; } } } diff --git a/src/LibHac/Crypto/Detail/AesCtrMode.cs b/src/LibHac/Crypto/Detail/AesCtrMode.cs index 7ed80a93..c9a38a01 100644 --- a/src/LibHac/Crypto/Detail/AesCtrMode.cs +++ b/src/LibHac/Crypto/Detail/AesCtrMode.cs @@ -1,6 +1,7 @@ using System; using System.Buffers.Binary; using System.Diagnostics; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security.Cryptography; using LibHac.Common; @@ -10,7 +11,7 @@ namespace LibHac.Crypto.Detail public struct AesCtrMode { private AesCore _aesCore; - private byte[] _counter; + public Buffer16 Iv; public void Initialize(ReadOnlySpan key, ReadOnlySpan iv) { @@ -19,7 +20,7 @@ namespace LibHac.Crypto.Detail _aesCore = new AesCore(); _aesCore.Initialize(key, ReadOnlySpan.Empty, CipherMode.ECB, false); - _counter = iv.ToArray(); + Iv = Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(iv)); } public void Transform(ReadOnlySpan input, Span output) @@ -28,7 +29,7 @@ namespace LibHac.Crypto.Detail int length = blockCount * Aes.BlockSize; using var counterBuffer = new RentedArray(length); - FillDecryptedCounter(_counter, counterBuffer.Span); + FillDecryptedCounter(Iv, counterBuffer.Span); _aesCore.Encrypt(counterBuffer.Array, counterBuffer.Array, length); Util.XorArrays(output, input, counterBuffer.Span); diff --git a/src/LibHac/Crypto/Detail/AesCtrModeNi.cs b/src/LibHac/Crypto/Detail/AesCtrModeNi.cs index db5802bf..02781901 100644 --- a/src/LibHac/Crypto/Detail/AesCtrModeNi.cs +++ b/src/LibHac/Crypto/Detail/AesCtrModeNi.cs @@ -14,7 +14,7 @@ namespace LibHac.Crypto.Detail private AesCoreNi _aesCore; #pragma warning restore 649 - private Vector128 _iv; + public Vector128 Iv; public void Initialize(ReadOnlySpan key, ReadOnlySpan iv) { @@ -22,7 +22,7 @@ namespace LibHac.Crypto.Detail _aesCore.Initialize(key, false); - _iv = Unsafe.ReadUnaligned>(ref MemoryMarshal.GetReference(iv)); + Iv = Unsafe.ReadUnaligned>(ref MemoryMarshal.GetReference(iv)); } public void Transform(ReadOnlySpan input, Span output) @@ -36,7 +36,7 @@ namespace LibHac.Crypto.Detail Vector128 byteSwapMask = Vector128.Create((ulong)0x706050403020100, 0x8090A0B0C0D0E0F).AsByte(); Vector128 inc = Vector128.Create((ulong)0, 1); - Vector128 iv = _iv; + Vector128 iv = Iv; Vector128 bSwappedIv = Ssse3.Shuffle(iv, byteSwapMask).AsUInt64(); while (remaining >= 8 * Aes.BlockSize) @@ -99,7 +99,7 @@ namespace LibHac.Crypto.Detail remaining -= Aes.BlockSize; } - _iv = iv; + Iv = iv; if (remaining != 0) { @@ -110,7 +110,7 @@ namespace LibHac.Crypto.Detail private void EncryptCtrPartialBlock(ReadOnlySpan input, Span output) { Span counter = stackalloc byte[0x10]; - Unsafe.WriteUnaligned(ref counter[0], _iv); + Unsafe.WriteUnaligned(ref counter[0], Iv); _aesCore.Encrypt(counter, counter); diff --git a/src/LibHac/Crypto/Detail/AesXtsMode.cs b/src/LibHac/Crypto/Detail/AesXtsMode.cs index 2fad3d11..a0c54cc9 100644 --- a/src/LibHac/Crypto/Detail/AesXtsMode.cs +++ b/src/LibHac/Crypto/Detail/AesXtsMode.cs @@ -11,7 +11,7 @@ namespace LibHac.Crypto.Detail { private AesCore _dataAesCore; private AesCore _tweakAesCore; - private byte[] _iv; + public Buffer16 Iv; public void Initialize(ReadOnlySpan key1, ReadOnlySpan key2, ReadOnlySpan iv, bool isDecrypting) { @@ -23,7 +23,7 @@ namespace LibHac.Crypto.Detail _dataAesCore.Initialize(key1, ReadOnlySpan.Empty, CipherMode.ECB, isDecrypting); _tweakAesCore.Initialize(key2, ReadOnlySpan.Empty, CipherMode.ECB, false); - _iv = iv.ToArray(); + Iv = Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(iv)); } public void Encrypt(ReadOnlySpan input, Span output) @@ -38,7 +38,7 @@ namespace LibHac.Crypto.Detail var tweak = new Buffer16(); - _tweakAesCore.Encrypt(_iv, tweak); + _tweakAesCore.Encrypt(Iv, tweak); using var tweakBuffer = new RentedArray(blockCount * Aes.BlockSize); tweak = FillTweakBuffer(tweak, MemoryMarshal.Cast(tweakBuffer.Span)); @@ -90,7 +90,7 @@ namespace LibHac.Crypto.Detail var tweak = new Buffer16(); - _tweakAesCore.Encrypt(_iv, tweak); + _tweakAesCore.Encrypt(Iv, tweak); if (blockCount > 0) { diff --git a/src/LibHac/Crypto/Detail/AesXtsModeNi.cs b/src/LibHac/Crypto/Detail/AesXtsModeNi.cs index 897ba171..69c76b98 100644 --- a/src/LibHac/Crypto/Detail/AesXtsModeNi.cs +++ b/src/LibHac/Crypto/Detail/AesXtsModeNi.cs @@ -16,7 +16,7 @@ namespace LibHac.Crypto.Detail private AesCoreNi _tweakAesCore; #pragma warning restore 649 - private Vector128 _iv; + public Vector128 Iv; public void Initialize(ReadOnlySpan key1, ReadOnlySpan key2, ReadOnlySpan iv, bool decrypting) { @@ -25,7 +25,7 @@ namespace LibHac.Crypto.Detail _dataAesCore.Initialize(key1, decrypting); _tweakAesCore.Initialize(key2, false); - _iv = Unsafe.ReadUnaligned>(ref MemoryMarshal.GetReference(iv)); + Iv = Unsafe.ReadUnaligned>(ref MemoryMarshal.GetReference(iv)); } public void Encrypt(ReadOnlySpan input, Span output) @@ -41,7 +41,7 @@ namespace LibHac.Crypto.Detail Vector128 mask = Vector128.Create(0x87, 1).AsByte(); - Vector128 tweak = _tweakAesCore.EncryptBlock(_iv); + Vector128 tweak = _tweakAesCore.EncryptBlock(Iv); while (remainingBlocks > 7) { @@ -121,7 +121,7 @@ namespace LibHac.Crypto.Detail Vector128 mask = Vector128.Create(0x87, 1).AsByte(); - Vector128 tweak = _tweakAesCore.EncryptBlock(_iv); + Vector128 tweak = _tweakAesCore.EncryptBlock(Iv); while (remainingBlocks > 7) { diff --git a/src/LibHac/Crypto/ICipher.cs b/src/LibHac/Crypto/ICipher.cs index 9973d7f8..c9df0a06 100644 --- a/src/LibHac/Crypto/ICipher.cs +++ b/src/LibHac/Crypto/ICipher.cs @@ -1,4 +1,5 @@ using System; +using LibHac.Common; namespace LibHac.Crypto { @@ -6,4 +7,9 @@ namespace LibHac.Crypto { void Transform(ReadOnlySpan input, Span output); } + + public interface ICipherWithIv : ICipher + { + ref Buffer16 Iv { get; } + } } \ No newline at end of file