using System; using System.Collections.Generic; using System.Linq; using LibHac.Crypto; using Xunit; namespace LibHac.Tests.CryptoTests { public class AesXtsTests { public static TheoryData EncryptTestVectors = RemovePartialByteTests(RspReader.ReadEncryptionTestVectors(true, "XTSGenAES128.rsp")); public static TheoryData DecryptTestVectors = RemovePartialByteTests(RspReader.ReadEncryptionTestVectors(false, "XTSGenAES128.rsp")); // The XTS implementation only supports multiples of whole bytes private static TheoryData RemovePartialByteTests(TheoryData input) { IEnumerable filteredTestVectors = input .Select(x => x[0]) .Cast() .Where(x => x.DataUnitLength % 8 == 0); var output = new TheoryData(); foreach (EncryptionTestVector item in filteredTestVectors) { output.Add(item); } return output; } [Theory] [MemberData(nameof(EncryptTestVectors))] public static void Encrypt(EncryptionTestVector tv) { Span key1 = tv.Key.AsSpan(0, 0x10); Span key2 = tv.Key.AsSpan(0x10, 0x10); Common.CipherTestCore(tv.PlainText, tv.CipherText, Aes.CreateXtsEncryptor(key1, key2, tv.Iv, true)); } [Theory] [MemberData(nameof(DecryptTestVectors))] public static void Decrypt(EncryptionTestVector tv) { Span key1 = tv.Key.AsSpan(0, 0x10); Span key2 = tv.Key.AsSpan(0x10, 0x10); Common.CipherTestCore(tv.CipherText, tv.PlainText, Aes.CreateXtsDecryptor(key1, key2, tv.Iv, true)); } [AesIntrinsicsRequiredTheory] [MemberData(nameof(EncryptTestVectors))] public static void EncryptIntrinsics(EncryptionTestVector tv) { Span key1 = tv.Key.AsSpan(0, 0x10); Span key2 = tv.Key.AsSpan(0x10, 0x10); Common.CipherTestCore(tv.PlainText, tv.CipherText, Aes.CreateXtsEncryptor(key1, key2, tv.Iv)); } [AesIntrinsicsRequiredTheory] [MemberData(nameof(DecryptTestVectors))] public static void DecryptIntrinsics(EncryptionTestVector tv) { Span key1 = tv.Key.AsSpan(0, 0x10); Span key2 = tv.Key.AsSpan(0x10, 0x10); Common.CipherTestCore(tv.CipherText, tv.PlainText, Aes.CreateXtsDecryptor(key1, key2, tv.Iv)); } } }