diff options
author | Debayan Ghosh <debayang.qdt@qualcommdatacenter.com> | 2018-02-28 21:56:03 +0530 |
---|---|---|
committer | Debayan Ghosh <debayang.qdt@qualcommdatacenter.com> | 2018-02-28 21:56:03 +0530 |
commit | 68e96e4593dff69d202f6b8b1faf42fb7875c7dc (patch) | |
tree | ad721f6afa3297da18f183a5b67acb43fb645cf4 /tests/src | |
parent | a332497a021c35d17079522eebb26680173962dd (diff) | |
download | coreclr-68e96e4593dff69d202f6b8b1faf42fb7875c7dc.tar.gz coreclr-68e96e4593dff69d202f6b8b1faf42fb7875c7dc.tar.bz2 coreclr-68e96e4593dff69d202f6b8b1faf42fb7875c7dc.zip |
ARM64 Crypto intrinsics tests for AES/SHA1/SHA256
Diffstat (limited to 'tests/src')
-rw-r--r-- | tests/src/JIT/HardwareIntrinsics/Arm64/Crypto.cs | 338 | ||||
-rw-r--r-- | tests/src/JIT/HardwareIntrinsics/Arm64/Crypto.csproj | 34 |
2 files changed, 372 insertions, 0 deletions
diff --git a/tests/src/JIT/HardwareIntrinsics/Arm64/Crypto.cs b/tests/src/JIT/HardwareIntrinsics/Arm64/Crypto.cs new file mode 100644 index 0000000000..a1720d9715 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/Arm64/Crypto.cs @@ -0,0 +1,338 @@ +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +#if ARM64_SIMD_API_PENDING_APPROVAL_AND_OR_COREFX_MERGE +using System.Runtime.Intrinsics.Arm.Arm64; +#endif //ARM64_SIMD_API_PENDING_APPROVAL_AND_OR_COREFX_MERGE + +namespace Arm64intrisicsTest +{ + + class Program + { + + struct DataSet<TBaseType, TVectorType> + where TBaseType : struct + where TVectorType : new() + { + private static TVectorType _vectorX; + private static TVectorType _vectorY; + private static TVectorType _vectorZ; + + public static TVectorType vectorX { get { return _vectorX; }} + public static TVectorType vectorY { get { return _vectorY; }} + public static TVectorType vectorZ { get { return _vectorZ; }} + + public static TBaseType[] arrayX { get; private set; } + public static TBaseType[] arrayY { get; private set; } + public static TBaseType[] arrayZ { get; private set; } + + public static unsafe void setData(TBaseType[] x, TBaseType[] y) + { + arrayX = x; + arrayY = y; + + GCHandle handleSrc = GCHandle.Alloc(x, GCHandleType.Pinned); + + try + { + var ptrSrc = (byte*) handleSrc.AddrOfPinnedObject().ToPointer(); + + _vectorX = Unsafe.Read<TVectorType>(ptrSrc); + } + finally + { + handleSrc.Free(); + } + + handleSrc = GCHandle.Alloc(y, GCHandleType.Pinned); + + try + { + var ptrSrc = (byte*) handleSrc.AddrOfPinnedObject().ToPointer(); + + _vectorY = Unsafe.Read<TVectorType>(ptrSrc); + } + finally + { + handleSrc.Free(); + } + } + + public static unsafe void setData(TBaseType[] x, TBaseType[] y, TBaseType[] z) + { + setData(x, y); + arrayZ = z; + + GCHandle handleSrc = GCHandle.Alloc(z, GCHandleType.Pinned); + + try + { + var ptrSrc = (byte*) handleSrc.AddrOfPinnedObject().ToPointer(); + + _vectorZ = Unsafe.Read<TVectorType>(ptrSrc); + } + finally + { + handleSrc.Free(); + } + + } + + } + + static unsafe TBaseType[] writeVector<TBaseType, TVectorType>(TVectorType src) + where TBaseType : struct + where TVectorType : new() + { + var length = Unsafe.SizeOf<TVectorType>() / Unsafe.SizeOf<TBaseType>(); + var dst = new TBaseType[length]; + + GCHandle handleSrc = GCHandle.Alloc(src, GCHandleType.Pinned); + GCHandle handleDst = GCHandle.Alloc(dst, GCHandleType.Pinned); + + try + { + var ptrSrc = (byte*) handleSrc.AddrOfPinnedObject().ToPointer(); + var ptrDst = (byte*) handleDst.AddrOfPinnedObject().ToPointer(); + + for (int i = 0; i < Unsafe.SizeOf<TVectorType>(); ++i) + { + ptrDst[i] = ptrSrc[i]; + } + } + finally + { + handleSrc.Free(); + handleDst.Free(); + } + + return dst; + } + + static void testCryptoOp<TBaseType, TVectorType, TBaseReturnType, TVectorReturnType>(String testCaseDescription, + Func<TVectorType, TVectorType, TVectorType, TVectorReturnType> cryptoOp, + TBaseType[] check) + where TBaseType : struct, IComparable + where TVectorType : new() + where TBaseReturnType : struct, IComparable + where TVectorReturnType : new() + { + bool failed = false; + try + { + var vX = DataSet<TBaseType, TVectorType>.vectorX; + var vY = DataSet<TBaseType, TVectorType>.vectorY; + var vZ = DataSet<TBaseType, TVectorType>.vectorZ; + var vResult = cryptoOp(vX, vY, vZ); + + var result = writeVector<TBaseReturnType, TVectorReturnType>(vResult); + //Console.WriteLine("res [{0}]", string.Join(", ", result)); + + + for (int i = 0; i < result.Length; i++) + { + + var expected = check[i]; + + if (result[i].CompareTo(expected) != 0) + { + if(!failed) + { + Console.WriteLine($"testCryptoOp<{typeof(TBaseType).Name}, {typeof(TVectorType).Name} >{testCaseDescription}: Check Failed"); + } + Console.WriteLine($"check[{i}] : result[{i}] = {result[i]}, expected {expected}"); + failed = true; + } + } + } + catch + { + Console.WriteLine($"testCryptoOp<{typeof(TBaseType).Name}, {typeof(TVectorType).Name} >{testCaseDescription}: Unexpected exception"); + throw; + } + + if (failed) + { + throw new Exception($"testCryptoOp<{typeof(TBaseType).Name}, {typeof(TVectorType).Name} >{testCaseDescription}: Failed"); + } + else + { + Console.WriteLine($"testCryptoOp<{typeof(TBaseType).Name}, {typeof(TVectorType).Name} >{testCaseDescription}: Check Passed"); + } + } + + static void testThrowsTypeNotSupported<TVectorType>(String testCaseDescription, + Func<TVectorType, TVectorType, TVectorType, TVectorType> cryptoOp) + where TVectorType : new() + { + TVectorType v = new TVectorType(); + + bool notSupported = false; + + try + { + cryptoOp(v,v,v); + } + catch (PlatformNotSupportedException) + { + notSupported = true; + } + finally + { + Debug.Assert(notSupported, $"{typeof(TVectorType).Name} {testCaseDescription}: Failed to throw PlatformNotSupportedException"); + } + } + + static void testThrowsPlatformNotSupported<TVectorType>(String testCaseDescription, + Func<TVectorType, TVectorType, TVectorType, TVectorType> cryptoOp) + where TVectorType : new() + { + testThrowsPlatformNotSupported<TVectorType, TVectorType>(testCaseDescription, cryptoOp); + } + + static void testThrowsPlatformNotSupported<TVectorType, TVectorTypeReturn>(String testCaseDescription, + Func<TVectorType, TVectorType, TVectorType, TVectorTypeReturn> cryptoOp) + where TVectorType : new() + { + TVectorType v = new TVectorType(); + + bool notSupported = false; + + try + { + cryptoOp(v,v,v); + } + catch (PlatformNotSupportedException) // TODO-Fixme check for Type not supported exception + { + notSupported = true; + } + finally + { + Debug.Assert(notSupported, $"{typeof(TVectorType).Name} {testCaseDescription}: Failed to throw TypeNotSupportedException"); + } + } + + + static void TestAes() + { +#if ARM64_SIMD_API_PENDING_APPROVAL_AND_OR_COREFX_MERGE + String name = "Aes"; + + if (Aes.IsSupported) + { + testCryptoOp<byte, Vector128<byte>, byte, Vector128<byte> >(name, (x, y, z) => Aes.Encrypt(x, y), aesEncRes); + testCryptoOp<byte, Vector128<byte>, byte, Vector128<byte> >(name, (x, y, z) => Aes.Decrypt(x, y), aesDecRes); + testCryptoOp<byte, Vector128<byte>, byte, Vector128<byte> >(name, (x, y, z) => Aes.MixColumns(x), aesMixRes ); + testCryptoOp<byte, Vector128<byte>, byte, Vector128<byte> >(name, (x, y, z) => Aes.InverseMixColumns(x), aesInvMixRes ); + + } + else + { + testThrowsPlatformNotSupported<Vector128<byte> , Vector128<byte> >(name, (x, y, z) => Aes.Encrypt(x,y)); + testThrowsPlatformNotSupported<Vector128<byte> , Vector128<byte> >(name, (x, y, z) => Aes.Decrypt(x,y)); + testThrowsPlatformNotSupported<Vector128<byte> , Vector128<byte> >(name, (x, y, z) => Aes.MixColumns(x)); + testThrowsPlatformNotSupported<Vector128<byte> , Vector128<byte> >(name, (x, y, z) => Aes.InverseMixColumns(x)); + } +#endif //ARM64_SIMD_API_PENDING_APPROVAL_AND_OR_COREFX_MERGE + } + + static void TestSha256() + { +#if ARM64_SIMD_API_PENDING_APPROVAL_AND_OR_COREFX_MERGE + String name = "Sha256"; + if (Sha256.IsSupported) + { + testCryptoOp<uint, Vector128<uint>, uint, Vector128<uint> >(name, (x, y, z) => Sha256.HashLower(x, y, z), sha256low); + testCryptoOp<uint, Vector128<uint>, uint, Vector128<uint> >(name, (x, y, z) => Sha256.HashUpper(x, y, z), sha256high); + testCryptoOp<uint, Vector128<uint>, uint, Vector128<uint> >(name, (x, y, z) => Sha256.SchedulePart1(x, y), sha256su1Res); + testCryptoOp<uint, Vector128<uint>, uint, Vector128<uint> >(name, (x, y, z) => Sha256.SchedulePart2(x, y, z), sha256su2Res); + } + else + { + testThrowsPlatformNotSupported<Vector128<uint>, Vector128<uint> >(name, (x, y, z) => Sha256.HashLower(x, y, z)); + testThrowsPlatformNotSupported<Vector128<uint>, Vector128<uint> >(name, (x, y, z) => Sha256.HashUpper(x, y, z)); + testThrowsPlatformNotSupported<Vector128<uint>, Vector128<uint> >(name, (x, y, z) => Sha256.SchedulePart1(x, y)); + testThrowsPlatformNotSupported<Vector128<uint>, Vector128<uint> >(name, (x, y, z) => Sha256.SchedulePart2(x, y, z)); + } +#endif //ARM64_SIMD_API_PENDING_APPROVAL_AND_OR_COREFX_MERGE + } + + static void TestSha1() + { +#if ARM64_SIMD_API_PENDING_APPROVAL_AND_OR_COREFX_MERGE + String name = "Sha1"; + if (Sha1.IsSupported) + { + testCryptoOp<uint, Vector128<uint>, uint, Vector128<uint> >(name, (x, y, z) => Sha1.HashChoose(x, 20, y), sha1cRes); + testCryptoOp<uint, Vector128<uint>, uint, Vector128<uint> >(name, (x, y, z) => Sha1.HashParity(x, 20, y), sha1pRes); + testCryptoOp<uint, Vector128<uint>, uint, Vector128<uint> >(name, (x, y, z) => Sha1.HashMajority(x, 20, y), sha1mRes); + testCryptoOp<uint, Vector128<uint>, uint, Vector128<uint> >(name, (x, y, z) => Sha1.SchedulePart1(x, y, z), sha1su1Res); + testCryptoOp<uint, Vector128<uint>, uint, Vector128<uint> >(name, (x, y, z) => Sha1.SchedulePart2(x, y), sha1su2Res); + if(Sha1.FixedRotate(100) != 25) + throw new Exception("Sha1 FixedRotate failed.\n"); + + + } + else + { + testThrowsPlatformNotSupported<Vector128<uint> , Vector128<uint> >(name, (x, y, z) => Sha1.HashChoose(x, 20, y)); + testThrowsPlatformNotSupported<Vector128<uint> , Vector128<uint> >(name, (x, y, z) => Sha1.HashParity(x, 20, y)); + testThrowsPlatformNotSupported<Vector128<uint> , Vector128<uint> >(name, (x, y, z) => Sha1.HashMajority(x, 20, y)); + testThrowsPlatformNotSupported<Vector128<uint> , Vector128<uint> >(name, (x, y, z) => Sha1.SchedulePart1(x, y, z)); + testThrowsPlatformNotSupported<Vector128<uint> , Vector128<uint> >(name, (x, y, z) => Sha1.SchedulePart2(x, y)); + } +#endif //ARM64_SIMD_API_PENDING_APPROVAL_AND_OR_COREFX_MERGE + } + + static void initializeDataSetDefault() + { + /// Data sets + DataSet<byte, Vector128<byte> >.setData(new byte[] { 1, 5, 100, 0, 7, 8, 2, 9, 1, 5, 100, 0, 7, 8, 2, 9 }, + new byte[] { 22, 1, 50, 0, 7, 5, 3, 33, 17, 4, 100, 120, 27, 6, 2, 6 }, + new byte[] { 1, 5, 10, 0, 17, 23, 14, 33, 15, 40, 0, 20, 22, 55, 12, 5 }); + DataSet<uint, Vector128<uint> >.setData(new uint[] {10, 44, 11, 81}, new uint[] {20, 41, 67, 59}, new uint[] {10, 20, 51, 96}); + } + + // Below result values are obtained by executing the corresponding GCC arm64 crypto intrinsics (defined in arm_neon.h) + // with the same input dataset on ARM64 platform. + + static byte[] aesEncRes = new byte[] {240, 215, 99, 118, 99, 124, 99, 99, 202, 171, 177, 52, 156, 242, 124, 188}; + static byte[] aesDecRes = new byte[] {135, 215, 82, 238, 82, 48, 82, 193, 124, 243, 185, 251, 196, 09, 09, 82}; + static byte[] aesMixRes = new byte[] {105, 167, 204, 98, 29, 24, 16, 17, 105, 167, 204, 98, 29, 24, 16, 17}; + static byte[] aesInvMixRes = new byte[] {203, 158, 110, 91, 41, 60, 36, 53, 203, 158, 110, 91, 41, 60, 36, 53}; + static uint[] sha1cRes = new uint[] {2162335592, 464120, 1073745449, 1073741936}; + static uint[] sha1pRes = new uint[] {15831335, 2147977893, 3857, 2147483767}; + static uint[] sha1mRes = new uint[] {12230250, 382193, 1073744809, 1073741916}; + static uint[] sha1su1Res = new uint[] {11, 105, 44, 24}; + static uint[] sha1su2Res = new uint[] {70,222,96,46}; + static uint[] sha256low = new uint[] {3870443882, 98061066, 1597900421, 3536859796}; + static uint[] sha256high = new uint[] {2024066181, 3259295072, 1866655758, 692061599}; + static uint[] sha256su1Res = new uint[] {1477115919, 369279021, 2719236117, 671416403}; + static uint[] sha256su2Res = new uint[] {2089011, 3932271, 203417658, 2151313268}; + + + static void ExecuteAllTests() + { + TestAes(); + TestSha1(); + TestSha256(); + } + + static int Main(string[] args) + { +#if ARM64_SIMD_API_PENDING_APPROVAL_AND_OR_COREFX_MERGE + Console.WriteLine($"System.Runtime.Intrinsics.Arm.Arm64.Aes.IsSupported = {Aes.IsSupported}"); + Console.WriteLine($"System.Runtime.Intrinsics.Arm.Arm64.Sha1.IsSupported = {Sha1.IsSupported}"); + Console.WriteLine($"System.Runtime.Intrinsics.Arm.Arm64.Sha2.IsSupported = {Sha256.IsSupported}"); +#endif //ARM64_SIMD_API_PENDING_APPROVAL_AND_OR_COREFX_MERGE + initializeDataSetDefault(); + Console.WriteLine("Running tests"); + ExecuteAllTests(); + + return 100; + } + } +} diff --git a/tests/src/JIT/HardwareIntrinsics/Arm64/Crypto.csproj b/tests/src/JIT/HardwareIntrinsics/Arm64/Crypto.csproj new file mode 100644 index 0000000000..fa5f43a970 --- /dev/null +++ b/tests/src/JIT/HardwareIntrinsics/Arm64/Crypto.csproj @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <SchemaVersion>2.0</SchemaVersion> + <OutputType>Exe</OutputType> + <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + </PropertyGroup> + <!-- Default configurations to help VS understand the configurations --> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " /> + <ItemGroup> + <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> + <Visible>False</Visible> + </CodeAnalysisDependentAssemblyPaths> + </ItemGroup> + <PropertyGroup> + <DebugType>None</DebugType> + <Optimize>True</Optimize> + </PropertyGroup> + <ItemGroup> + <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Crypto.cs" /> + </ItemGroup> + <ItemGroup> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> + <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup> +</Project> |