Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/390 aes #8

Draft
wants to merge 13 commits into
base: develop
Choose a base branch
from
82 changes: 82 additions & 0 deletions src/IKVM.Java/map.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1638,6 +1638,88 @@
</body>
</method>
</class>
<class name="com.sun.crypto.provider.AESCrypt">
<method name="decryptBlock" sig="([BI[BI)V">
<prologue>
<ldarg_1 />
<ldarg_2 />
<ldarg_3 />
<ldarg_s argNum="4" />
<ldarg_0 />
<ldfld class="com.sun.crypto.provider.AESCrypt" name="K" sig="[I" />
<!-- bool AESCrypt.DecryptBlock(byte[] in, int inOffset, byte[] out, int outOffset, int[] K) -->
<call type="IKVM.Java.Externs.com.sun.crypto.provider.AESCrypt" name="DecryptBlock" sig="([BI[BI[I)Z" />
<brfalse name="continue" />
<ret />
<label name="continue" />
</prologue>
</method>
<method name="encryptBlock" sig="([BI[BI)V">
<prologue>
<ldarg_1 />
<ldarg_2 />
<ldarg_3 />
<ldarg_s argNum="4" />
<ldarg_0 />
<ldfld class="com.sun.crypto.provider.AESCrypt" name="K" sig="[I" />
<!-- bool AESCrypt.EncryptBlock(byte[] in, int inOffset, byte[] out, int outOffset, int[] K) -->
<call type="IKVM.Java.Externs.com.sun.crypto.provider.AESCrypt" name="EncryptBlock" sig="([BI[BI[I)Z" />
<brfalse name="continue" />
<ret />
<label name="continue" />
</prologue>
</method>
</class>
<class name="com.sun.crypto.provider.GHASH">
<method name="processBlocks" sig="([BII[J[J)V">
<prologue>
<ldarg_0 />
<ldarg_1 />
<ldarg_2 />
<ldarg_3 />
<ldarg_s argNum="4" />
<!-- bool GHASH.ProcessBlocks(byte[] data, int inOffs, int blocks, long[] state, long[] subH) -->
<call type="IKVM.Java.Externs.com.sun.crypto.provider.GHASH" name="ProcessBlocks" sig="([BII[J[J)Z" />
<brfalse name="continue" />
<ret />
<label name="continue" />
</prologue>
</method>
</class>
<class name="com.sun.crypto.provider.CipherBlockChaining">
<method name="implDecrypt" sig="([BII[BI)I">
<prologue>
<ldarg_0 />
<ldarg_1 />
<ldarg_2 />
<ldarg_3 />
<ldarg_s argNum="4" />
<ldarg_s argNum="5" />
<!-- bool CipherBlockChaining.DecryptAESCrypt(object self, byte[] cipher, int cipherOffset, int cipherLen, byte[] plain, int plainOffset, ) -->
<call type="IKVM.Java.Externs.com.sun.crypto.provider.CipherBlockChaining" name="DecryptAESCrypt" sig="(Ljava.lang.Object;[BII[BI)Z" />
<brfalse name="continue" />
<ldarg_3 />
<ret />
<label name="continue" />
</prologue>
</method>
<method name="implEncrypt" sig="([BII[BI)I">
<prologue>
<ldarg_0 />
<ldarg_1 />
<ldarg_2 />
<ldarg_3 />
<ldarg_s argNum="4" />
<ldarg_s argNum="5" />
<!-- bool CipherBlockChaining.EncryptAESCrypt(object self, byte[] plain, int plainOffset, int plainLen, byte[] cipher, int cipherOffset) -->
<call type="IKVM.Java.Externs.com.sun.crypto.provider.CipherBlockChaining" name="EncryptAESCrypt" sig="(Ljava.lang.Object;[BII[BI)Z" />
<brfalse name="continue" />
<ldarg_3 />
<ret />
<label name="continue" />
</prologue>
</method>
</class>
<!-- This is where the "native" helper methods start -->
<class name="ikvm.lang.CIL">
<method name="unbox_byte" sig="(Ljava.lang.Object;)B">
Expand Down
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 src/IKVM.Runtime/Java/Externs/com/sun/crypto/provider/AESCrypt.X86.cs
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 src/IKVM.Runtime/Java/Externs/com/sun/crypto/provider/AESCrypt.cs
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;
}
}
Loading
Loading