Add ICipherWithIv interface

This commit is contained in:
Alex Barney 2019-11-25 11:05:09 -06:00
parent 99522b748e
commit f9232b9f12
12 changed files with 68 additions and 34 deletions

View File

@ -67,7 +67,7 @@ namespace LibHac.Crypto
return new AesCbcEncryptor(key, iv);
}
public static ICipher CreateCtrDecryptor(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv, bool preferDotNetCrypto = false)
public static ICipherWithIv CreateCtrDecryptor(ReadOnlySpan<byte> key, ReadOnlySpan<byte> 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<byte> key, ReadOnlySpan<byte> iv, bool preferDotNetCrypto = false)
public static ICipherWithIv CreateCtrEncryptor(ReadOnlySpan<byte> key, ReadOnlySpan<byte> 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<byte> key1, ReadOnlySpan<byte> key2,
public static ICipherWithIv CreateXtsDecryptor(ReadOnlySpan<byte> key1, ReadOnlySpan<byte> key2,
ReadOnlySpan<byte> 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<byte> key1, ReadOnlySpan<byte> key2,
public static ICipherWithIv CreateXtsEncryptor(ReadOnlySpan<byte> key1, ReadOnlySpan<byte> key2,
ReadOnlySpan<byte> iv, bool preferDotNetCrypto = false)
{
#if HAS_INTRINSICS

View File

@ -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<Vector128<byte>, Buffer16>(ref _baseCipher.Iv);
public AesCbcEncryptorNi(ReadOnlySpan<byte> key, ReadOnlySpan<byte> 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<Vector128<byte>, Buffer16>(ref _baseCipher.Iv);
public AesCbcDecryptorNi(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv)
{
_baseCipher = new AesCbcModeNi();

View File

@ -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<byte> key, ReadOnlySpan<byte> iv)
{
_baseCipher = new AesCtrMode();

View File

@ -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<Vector128<byte>, Buffer16>(ref _baseCipher.Iv);
public AesCtrCipherNi(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv)
{
_baseCipher = new AesCtrModeNi();

View File

@ -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<byte> key1, ReadOnlySpan<byte> key2, ReadOnlySpan<byte> 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<byte> key1, ReadOnlySpan<byte> key2, ReadOnlySpan<byte> iv)
{

View File

@ -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<Vector128<byte>, Buffer16>(ref _baseCipher.Iv);
public AesXtsEncryptorNi(ReadOnlySpan<byte> key1, ReadOnlySpan<byte> key2, ReadOnlySpan<byte> 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<Vector128<byte>, Buffer16>(ref _baseCipher.Iv);
public AesXtsDecryptorNi(ReadOnlySpan<byte> key1, ReadOnlySpan<byte> key2, ReadOnlySpan<byte> iv)
{
_baseCipher = new AesXtsModeNi();

View File

@ -14,7 +14,7 @@ namespace LibHac.Crypto.Detail
private AesCoreNi _aesCore;
#pragma warning restore 649
private Vector128<byte> _iv;
public Vector128<byte> Iv;
public void Initialize(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv, bool isDecrypting)
{
@ -22,7 +22,7 @@ namespace LibHac.Crypto.Detail
_aesCore.Initialize(key, isDecrypting);
_iv = Unsafe.ReadUnaligned<Vector128<byte>>(ref MemoryMarshal.GetReference(iv));
Iv = Unsafe.ReadUnaligned<Vector128<byte>>(ref MemoryMarshal.GetReference(iv));
}
public void Encrypt(ReadOnlySpan<byte> input, Span<byte> output)
@ -32,7 +32,7 @@ namespace LibHac.Crypto.Detail
ref Vector128<byte> inBlock = ref Unsafe.As<byte, Vector128<byte>>(ref MemoryMarshal.GetReference(input));
ref Vector128<byte> outBlock = ref Unsafe.As<byte, Vector128<byte>>(ref MemoryMarshal.GetReference(output));
Vector128<byte> iv = _iv;
Vector128<byte> 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<byte> input, Span<byte> output)
@ -54,7 +54,7 @@ namespace LibHac.Crypto.Detail
ref Vector128<byte> inBlock = ref Unsafe.As<byte, Vector128<byte>>(ref MemoryMarshal.GetReference(input));
ref Vector128<byte> outBlock = ref Unsafe.As<byte, Vector128<byte>>(ref MemoryMarshal.GetReference(output));
Vector128<byte> iv = _iv;
Vector128<byte> iv = Iv;
while (remainingBlocks > 7)
{
@ -106,7 +106,7 @@ namespace LibHac.Crypto.Detail
remainingBlocks -= 1;
}
_iv = iv;
Iv = iv;
}
}
}

View File

@ -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<byte> key, ReadOnlySpan<byte> iv)
{
@ -19,7 +20,7 @@ namespace LibHac.Crypto.Detail
_aesCore = new AesCore();
_aesCore.Initialize(key, ReadOnlySpan<byte>.Empty, CipherMode.ECB, false);
_counter = iv.ToArray();
Iv = Unsafe.ReadUnaligned<Buffer16>(ref MemoryMarshal.GetReference(iv));
}
public void Transform(ReadOnlySpan<byte> input, Span<byte> output)
@ -28,7 +29,7 @@ namespace LibHac.Crypto.Detail
int length = blockCount * Aes.BlockSize;
using var counterBuffer = new RentedArray<byte>(length);
FillDecryptedCounter(_counter, counterBuffer.Span);
FillDecryptedCounter(Iv, counterBuffer.Span);
_aesCore.Encrypt(counterBuffer.Array, counterBuffer.Array, length);
Util.XorArrays(output, input, counterBuffer.Span);

View File

@ -14,7 +14,7 @@ namespace LibHac.Crypto.Detail
private AesCoreNi _aesCore;
#pragma warning restore 649
private Vector128<byte> _iv;
public Vector128<byte> Iv;
public void Initialize(ReadOnlySpan<byte> key, ReadOnlySpan<byte> iv)
{
@ -22,7 +22,7 @@ namespace LibHac.Crypto.Detail
_aesCore.Initialize(key, false);
_iv = Unsafe.ReadUnaligned<Vector128<byte>>(ref MemoryMarshal.GetReference(iv));
Iv = Unsafe.ReadUnaligned<Vector128<byte>>(ref MemoryMarshal.GetReference(iv));
}
public void Transform(ReadOnlySpan<byte> input, Span<byte> output)
@ -36,7 +36,7 @@ namespace LibHac.Crypto.Detail
Vector128<byte> byteSwapMask = Vector128.Create((ulong)0x706050403020100, 0x8090A0B0C0D0E0F).AsByte();
Vector128<ulong> inc = Vector128.Create((ulong)0, 1);
Vector128<byte> iv = _iv;
Vector128<byte> iv = Iv;
Vector128<ulong> 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<byte> input, Span<byte> output)
{
Span<byte> counter = stackalloc byte[0x10];
Unsafe.WriteUnaligned(ref counter[0], _iv);
Unsafe.WriteUnaligned(ref counter[0], Iv);
_aesCore.Encrypt(counter, counter);

View File

@ -11,7 +11,7 @@ namespace LibHac.Crypto.Detail
{
private AesCore _dataAesCore;
private AesCore _tweakAesCore;
private byte[] _iv;
public Buffer16 Iv;
public void Initialize(ReadOnlySpan<byte> key1, ReadOnlySpan<byte> key2, ReadOnlySpan<byte> iv, bool isDecrypting)
{
@ -23,7 +23,7 @@ namespace LibHac.Crypto.Detail
_dataAesCore.Initialize(key1, ReadOnlySpan<byte>.Empty, CipherMode.ECB, isDecrypting);
_tweakAesCore.Initialize(key2, ReadOnlySpan<byte>.Empty, CipherMode.ECB, false);
_iv = iv.ToArray();
Iv = Unsafe.ReadUnaligned<Buffer16>(ref MemoryMarshal.GetReference(iv));
}
public void Encrypt(ReadOnlySpan<byte> input, Span<byte> 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<byte>(blockCount * Aes.BlockSize);
tweak = FillTweakBuffer(tweak, MemoryMarshal.Cast<byte, Buffer16>(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)
{

View File

@ -16,7 +16,7 @@ namespace LibHac.Crypto.Detail
private AesCoreNi _tweakAesCore;
#pragma warning restore 649
private Vector128<byte> _iv;
public Vector128<byte> Iv;
public void Initialize(ReadOnlySpan<byte> key1, ReadOnlySpan<byte> key2, ReadOnlySpan<byte> iv, bool decrypting)
{
@ -25,7 +25,7 @@ namespace LibHac.Crypto.Detail
_dataAesCore.Initialize(key1, decrypting);
_tweakAesCore.Initialize(key2, false);
_iv = Unsafe.ReadUnaligned<Vector128<byte>>(ref MemoryMarshal.GetReference(iv));
Iv = Unsafe.ReadUnaligned<Vector128<byte>>(ref MemoryMarshal.GetReference(iv));
}
public void Encrypt(ReadOnlySpan<byte> input, Span<byte> output)
@ -41,7 +41,7 @@ namespace LibHac.Crypto.Detail
Vector128<byte> mask = Vector128.Create(0x87, 1).AsByte();
Vector128<byte> tweak = _tweakAesCore.EncryptBlock(_iv);
Vector128<byte> tweak = _tweakAesCore.EncryptBlock(Iv);
while (remainingBlocks > 7)
{
@ -121,7 +121,7 @@ namespace LibHac.Crypto.Detail
Vector128<byte> mask = Vector128.Create(0x87, 1).AsByte();
Vector128<byte> tweak = _tweakAesCore.EncryptBlock(_iv);
Vector128<byte> tweak = _tweakAesCore.EncryptBlock(Iv);
while (remainingBlocks > 7)
{

View File

@ -1,4 +1,5 @@
using System;
using LibHac.Common;
namespace LibHac.Crypto
{
@ -6,4 +7,9 @@ namespace LibHac.Crypto
{
void Transform(ReadOnlySpan<byte> input, Span<byte> output);
}
public interface ICipherWithIv : ICipher
{
ref Buffer16 Iv { get; }
}
}