-
-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #650 from iterate-ch/feature/390-aes
AES HW Intrinsics (X86)
- Loading branch information
Showing
9 changed files
with
889 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
src/IKVM.Runtime/Accessors/Com/Sun/Crypto/Provider/AESCryptAccessor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
namespace IKVM.Runtime.Accessors.Com.Sun.Crypto.Provider; | ||
|
||
#if !(FIRST_PASS || EXPORTER || IMPORTER) | ||
|
||
internal sealed class AESCryptAccessor(AccessorTypeResolver resolver) | ||
: Accessor<com.sun.crypto.provider.AESCrypt>(resolver, "com.sun.crypto.provider.AESCrypt") | ||
{ | ||
private FieldAccessor<com.sun.crypto.provider.AESCrypt, int[]> k; | ||
|
||
public int[] K(com.sun.crypto.provider.AESCrypt self) => GetField(ref k, "K").GetValue(self); | ||
} | ||
|
||
#endif |
163 changes: 163 additions & 0 deletions
163
src/IKVM.Runtime/Java/Externs/com/sun/crypto/provider/AESCrypt.X86.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
#if NETCOREAPP3_0_OR_GREATER | ||
using System; | ||
using System.Runtime.CompilerServices; | ||
using System.Runtime.InteropServices; | ||
using System.Runtime.Intrinsics; | ||
using System.Runtime.Intrinsics.X86; | ||
|
||
namespace IKVM.Java.Externs.com.sun.crypto.provider.X86; | ||
|
||
internal abstract partial class AESCrypt | ||
{ | ||
public static bool IsSupported => Aes.IsSupported && Ssse3.IsSupported; | ||
|
||
protected static ReadOnlySpan<int> KeyShuffleMask => [0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f]; | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static void DecryptBlock(ReadOnlySpan<byte> from, Span<byte> to, ReadOnlySpan<int> key) | ||
{ | ||
// ext\openjdk\hotspot\src\cpu\x86\vm\stubGenerator_x86_32.cpp:3125-3210 | ||
Vector128<byte> xmm_temp1, xmm_temp2, xmm_temp3, xmm_temp4; | ||
#if NET8_0_OR_GREATER | ||
var xmm_key_shuf_mask = Vector128.LoadUnsafe(in MemoryMarshal.GetReference(KeyShuffleMask), 0).AsByte(); | ||
var xmm_result = Vector128.LoadUnsafe(in MemoryMarshal.GetReference(from)); | ||
#else | ||
var xmm_key_shuf_mask = Vector128Polyfill.LoadUnsafe(in MemoryMarshal.GetReference(KeyShuffleMask), 0).AsByte(); | ||
var xmm_result = Vector128Polyfill.LoadUnsafe(in MemoryMarshal.GetReference(from)); | ||
#endif | ||
|
||
xmm_temp1 = LoadKey(key, 0x10, xmm_key_shuf_mask); | ||
xmm_temp2 = LoadKey(key, 0x20, xmm_key_shuf_mask); | ||
xmm_temp3 = LoadKey(key, 0x30, xmm_key_shuf_mask); | ||
xmm_temp4 = LoadKey(key, 0x40, xmm_key_shuf_mask); | ||
|
||
xmm_result = Sse2.Xor(xmm_result, xmm_temp1); | ||
xmm_result = Aes.Decrypt(xmm_result, xmm_temp2); | ||
xmm_result = Aes.Decrypt(xmm_result, xmm_temp3); | ||
xmm_result = Aes.Decrypt(xmm_result, xmm_temp4); | ||
|
||
xmm_temp1 = LoadKey(key, 0x50, xmm_key_shuf_mask); | ||
xmm_temp2 = LoadKey(key, 0x60, xmm_key_shuf_mask); | ||
xmm_temp3 = LoadKey(key, 0x70, xmm_key_shuf_mask); | ||
xmm_temp4 = LoadKey(key, 0x80, xmm_key_shuf_mask); | ||
|
||
xmm_result = Aes.Decrypt(xmm_result, xmm_temp1); | ||
xmm_result = Aes.Decrypt(xmm_result, xmm_temp2); | ||
xmm_result = Aes.Decrypt(xmm_result, xmm_temp3); | ||
xmm_result = Aes.Decrypt(xmm_result, xmm_temp4); | ||
|
||
xmm_temp1 = LoadKey(key, 0x90, xmm_key_shuf_mask); | ||
xmm_temp2 = LoadKey(key, 0xa0, xmm_key_shuf_mask); | ||
xmm_temp3 = LoadKey(key, 0x00, xmm_key_shuf_mask); | ||
|
||
if (key.Length == 44) | ||
{ | ||
goto doLast; | ||
} | ||
|
||
xmm_result = Aes.Decrypt(xmm_result, xmm_temp1); | ||
xmm_result = Aes.Decrypt(xmm_result, xmm_temp2); | ||
|
||
xmm_temp1 = LoadKey(key, 0xb0, xmm_key_shuf_mask); | ||
xmm_temp2 = LoadKey(key, 0xc0, xmm_key_shuf_mask); | ||
|
||
if (key.Length == 52) | ||
{ | ||
goto doLast; | ||
} | ||
|
||
xmm_result = Aes.Decrypt(xmm_result, xmm_temp1); | ||
xmm_result = Aes.Decrypt(xmm_result, xmm_temp2); | ||
|
||
xmm_temp1 = LoadKey(key, 0xd0, xmm_key_shuf_mask); | ||
xmm_temp2 = LoadKey(key, 0xe0, xmm_key_shuf_mask); | ||
|
||
doLast:; | ||
xmm_result = Aes.Decrypt(xmm_result, xmm_temp1); | ||
xmm_result = Aes.Decrypt(xmm_result, xmm_temp2); | ||
xmm_result = Aes.DecryptLast(xmm_result, xmm_temp3); | ||
xmm_result.CopyTo(to); | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static void EncryptBlock(ReadOnlySpan<byte> from, Span<byte> to, ReadOnlySpan<int> key) | ||
{ | ||
// ext\openjdk\hotspot\src\cpu\x86\vm\stubGenerator_x86_32.cpp:2189-2277 | ||
Vector128<byte> xmm_temp1, xmm_temp2, xmm_temp3, xmm_temp4; | ||
#if NET8_0_OR_GREATER | ||
var xmm_key_shuf_mask = Vector128.LoadUnsafe(in MemoryMarshal.GetReference(KeyShuffleMask)).AsByte(); | ||
var xmm_result = Vector128.LoadUnsafe(in MemoryMarshal.GetReference(from)); | ||
#else | ||
var xmm_key_shuf_mask = Vector128Polyfill.LoadUnsafe(in MemoryMarshal.GetReference(KeyShuffleMask)).AsByte(); | ||
var xmm_result = Vector128Polyfill.LoadUnsafe(in MemoryMarshal.GetReference(from)); | ||
#endif | ||
|
||
xmm_temp1 = LoadKey(key, 0x00, xmm_key_shuf_mask); | ||
xmm_result = Sse2.Xor(xmm_result, xmm_temp1); | ||
|
||
xmm_temp1 = LoadKey(key, 0x10, xmm_key_shuf_mask); | ||
xmm_temp2 = LoadKey(key, 0x20, xmm_key_shuf_mask); | ||
xmm_temp3 = LoadKey(key, 0x30, xmm_key_shuf_mask); | ||
xmm_temp4 = LoadKey(key, 0x40, xmm_key_shuf_mask); | ||
|
||
xmm_result = Aes.Encrypt(xmm_result, xmm_temp1); | ||
xmm_result = Aes.Encrypt(xmm_result, xmm_temp2); | ||
xmm_result = Aes.Encrypt(xmm_result, xmm_temp3); | ||
xmm_result = Aes.Encrypt(xmm_result, xmm_temp4); | ||
|
||
xmm_temp1 = LoadKey(key, 0x50, xmm_key_shuf_mask); | ||
xmm_temp2 = LoadKey(key, 0x60, xmm_key_shuf_mask); | ||
xmm_temp3 = LoadKey(key, 0x70, xmm_key_shuf_mask); | ||
xmm_temp4 = LoadKey(key, 0x80, xmm_key_shuf_mask); | ||
|
||
xmm_result = Aes.Encrypt(xmm_result, xmm_temp1); | ||
xmm_result = Aes.Encrypt(xmm_result, xmm_temp2); | ||
xmm_result = Aes.Encrypt(xmm_result, xmm_temp3); | ||
xmm_result = Aes.Encrypt(xmm_result, xmm_temp4); | ||
|
||
xmm_temp1 = LoadKey(key, 0x90, xmm_key_shuf_mask); | ||
xmm_temp2 = LoadKey(key, 0xa0, xmm_key_shuf_mask); | ||
|
||
if (key.Length == 44) | ||
{ | ||
goto doLast; | ||
} | ||
|
||
xmm_result = Aes.Encrypt(xmm_result, xmm_temp1); | ||
xmm_result = Aes.Encrypt(xmm_result, xmm_temp2); | ||
|
||
xmm_temp1 = LoadKey(key, 0xb0, xmm_key_shuf_mask); | ||
xmm_temp2 = LoadKey(key, 0xc0, xmm_key_shuf_mask); | ||
|
||
if (key.Length == 52) | ||
{ | ||
goto doLast; | ||
} | ||
|
||
xmm_result = Aes.Encrypt(xmm_result, xmm_temp1); | ||
xmm_result = Aes.Encrypt(xmm_result, xmm_temp2); | ||
|
||
xmm_temp1 = LoadKey(key, 0xd0, xmm_key_shuf_mask); | ||
xmm_temp2 = LoadKey(key, 0xe0, xmm_key_shuf_mask); | ||
|
||
doLast:; | ||
xmm_result = Aes.Encrypt(xmm_result, xmm_temp1); | ||
xmm_result = Aes.EncryptLast(xmm_result, xmm_temp2); | ||
xmm_result.CopyTo(to); | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
protected static Vector128<byte> LoadKey(ReadOnlySpan<int> key, nuint offset, Vector128<byte>? shuffle_mask = null) | ||
{ | ||
#if NET8_0_OR_GREATER | ||
Vector128<byte> xmm_temp = Vector128.LoadUnsafe(in Unsafe.As<int, byte>(ref MemoryMarshal.GetReference(key)), offset); | ||
shuffle_mask ??= Vector128.LoadUnsafe(in MemoryMarshal.GetReference(KeyShuffleMask)).AsByte(); | ||
#else | ||
Vector128<byte> xmm_temp = Vector128Polyfill.LoadUnsafe(in Unsafe.As<int, byte>(ref MemoryMarshal.GetReference(key)), offset); | ||
shuffle_mask ??= Vector128Polyfill.LoadUnsafe(in MemoryMarshal.GetReference(KeyShuffleMask)).AsByte(); | ||
#endif | ||
|
||
return Ssse3.Shuffle(xmm_temp, shuffle_mask.Value); | ||
} | ||
} | ||
#endif |
37 changes: 37 additions & 0 deletions
37
src/IKVM.Runtime/Java/Externs/com/sun/crypto/provider/AESCrypt.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
using IKVM.Attributes; | ||
using System; | ||
using System.Runtime.CompilerServices; | ||
|
||
namespace IKVM.Java.Externs.com.sun.crypto.provider; | ||
|
||
[HideFromJava] | ||
internal static class AESCrypt | ||
{ | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static bool DecryptBlock(byte[] @in, int inOffset, byte[] @out, int outOffset, int[] K) | ||
{ | ||
#if NETCOREAPP3_0_OR_GREATER | ||
if (X86.AESCrypt.IsSupported) | ||
{ | ||
X86.AESCrypt.DecryptBlock(@in.AsSpan(inOffset), @out.AsSpan(outOffset), K); | ||
return true; | ||
} | ||
#endif | ||
|
||
return false; | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static bool EncryptBlock(byte[] @in, int inOffset, byte[] @out, int outOffset, int[] K) | ||
{ | ||
#if NETCOREAPP3_0_OR_GREATER | ||
if (X86.AESCrypt.IsSupported) | ||
{ | ||
X86.AESCrypt.EncryptBlock(@in.AsSpan(inOffset), @out.AsSpan(outOffset), K); | ||
return true; | ||
} | ||
#endif | ||
|
||
return false; | ||
} | ||
} |
Oops, something went wrong.