Mercurial > hg > graal-compiler
changeset 22994:7a9ffb0f17d9
AES decrypt stubs require an extra argument on SPARC
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Tue, 17 Nov 2015 01:58:18 +0100 |
parents | caea17af1094 |
children | 1fb858f97559 |
files | graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java |
diffstat | 6 files changed, 123 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java Mon Nov 16 14:22:56 2015 -0800 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java Tue Nov 17 01:58:18 2015 +0100 @@ -254,7 +254,22 @@ * {@code declaringClass} */ public void registerMethodSubstitution(Class<?> substituteDeclaringClass, String name, Class<?>... argumentTypes) { - MethodSubstitutionPlugin plugin = new MethodSubstitutionPlugin(substituteDeclaringClass, name, argumentTypes); + registerMethodSubstitution(substituteDeclaringClass, name, name, argumentTypes); + } + + /** + * Registers a plugin that implements a method based on the bytecode of a substitute method. + * + * @param substituteDeclaringClass the class declaring the substitute method + * @param name the name of both the original method + * @param substituteName the name of the substitute method + * @param argumentTypes the argument types of the method. Element 0 of this array must be + * the {@link Class} value for {@link InvocationPlugin.Receiver} iff the method + * is non-static. Upon returning, element 0 will have been rewritten to + * {@code declaringClass} + */ + public void registerMethodSubstitution(Class<?> substituteDeclaringClass, String name, String substituteName, Class<?>... argumentTypes) { + MethodSubstitutionPlugin plugin = new MethodSubstitutionPlugin(substituteDeclaringClass, substituteName, argumentTypes); plugins.register(plugin, false, allowOverwrite, declaringClass, name, argumentTypes); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Mon Nov 16 14:22:56 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Tue Nov 17 01:58:18 2015 +0100 @@ -132,6 +132,12 @@ public static final ForeignCallDescriptor DECRYPT_BLOCK = new ForeignCallDescriptor("decrypt_block", void.class, Word.class, Word.class, Pointer.class); /** + * @see AESCryptSubstitutions#decryptBlockStub(ForeignCallDescriptor, Word, Word, Pointer) + */ + public static final ForeignCallDescriptor DECRYPT_BLOCK_WITH_ORIGINAL_KEY = new ForeignCallDescriptor("decrypt_block_with_original_key", void.class, Word.class, Word.class, Pointer.class, + Pointer.class); + + /** * @see CipherBlockChainingSubstitutions#crypt */ public static final ForeignCallDescriptor ENCRYPT = new ForeignCallDescriptor("encrypt", void.class, Word.class, Word.class, Pointer.class, Pointer.class, int.class); @@ -142,6 +148,12 @@ public static final ForeignCallDescriptor DECRYPT = new ForeignCallDescriptor("decrypt", void.class, Word.class, Word.class, Pointer.class, Pointer.class, int.class); /** + * @see CipherBlockChainingSubstitutions#crypt + */ + public static final ForeignCallDescriptor DECRYPT_WITH_ORIGINAL_KEY = new ForeignCallDescriptor("decrypt_with_original_key", void.class, Word.class, Word.class, Pointer.class, Pointer.class, + int.class, Pointer.class); + + /** * @see VMErrorNode */ public static final ForeignCallDescriptor VM_ERROR = new ForeignCallDescriptor("vm_error", void.class, Object.class, Object.class, long.class);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Mon Nov 16 14:22:56 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Tue Nov 17 01:58:18 2015 +0100 @@ -293,17 +293,20 @@ assert config.aescryptDecryptBlockStub != 0L; assert config.cipherBlockChainingEncryptAESCryptStub != 0L; assert config.cipherBlockChainingDecryptAESCryptStub != 0L; + String arch = HotSpotVMConfig.config().getHostArchitectureName(); + String decryptSuffix = arch.equals("sparc") ? "WithOriginalKey" : ""; Class<?> c = MethodSubstitutionPlugin.resolveClass("com.sun.crypto.provider.CipherBlockChaining", true); if (c != null) { Registration r = new Registration(plugins, c); r.registerMethodSubstitution(CipherBlockChainingSubstitutions.class, cbcEncryptName, Receiver.class, byte[].class, int.class, int.class, byte[].class, int.class); - r.registerMethodSubstitution(CipherBlockChainingSubstitutions.class, cbcDecryptName, Receiver.class, byte[].class, int.class, int.class, byte[].class, int.class); + r.registerMethodSubstitution(CipherBlockChainingSubstitutions.class, cbcDecryptName, cbcDecryptName + decryptSuffix, Receiver.class, byte[].class, int.class, int.class, byte[].class, + int.class); } c = MethodSubstitutionPlugin.resolveClass("com.sun.crypto.provider.AESCrypt", true); if (c != null) { Registration r = new Registration(plugins, c); r.registerMethodSubstitution(AESCryptSubstitutions.class, aesEncryptName, Receiver.class, byte[].class, int.class, byte[].class, int.class); - r.registerMethodSubstitution(AESCryptSubstitutions.class, aesDecryptName, Receiver.class, byte[].class, int.class, byte[].class, int.class); + r.registerMethodSubstitution(AESCryptSubstitutions.class, aesDecryptName, aesDecryptName + decryptSuffix, Receiver.class, byte[].class, int.class, byte[].class, int.class); } } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Mon Nov 16 14:22:56 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Tue Nov 17 01:58:18 2015 +0100 @@ -30,7 +30,9 @@ import static com.oracle.graal.compiler.target.Backend.ARITHMETIC_SIN; import static com.oracle.graal.compiler.target.Backend.ARITHMETIC_TAN; import static com.oracle.graal.hotspot.HotSpotBackend.DECRYPT; +import static com.oracle.graal.hotspot.HotSpotBackend.DECRYPT_WITH_ORIGINAL_KEY; import static com.oracle.graal.hotspot.HotSpotBackend.DECRYPT_BLOCK; +import static com.oracle.graal.hotspot.HotSpotBackend.DECRYPT_BLOCK_WITH_ORIGINAL_KEY; import static com.oracle.graal.hotspot.HotSpotBackend.ENCRYPT; import static com.oracle.graal.hotspot.HotSpotBackend.ENCRYPT_BLOCK; import static com.oracle.graal.hotspot.HotSpotBackend.EXCEPTION_HANDLER; @@ -306,6 +308,8 @@ // These stubs do callee saving registerForeignCall(ENCRYPT_BLOCK, c.aescryptEncryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Byte)); registerForeignCall(DECRYPT_BLOCK, c.aescryptDecryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Byte)); + registerForeignCall(DECRYPT_BLOCK_WITH_ORIGINAL_KEY, c.aescryptDecryptBlockStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, + NamedLocationIdentity.getArrayLocation(JavaKind.Byte)); } catch (JVMCIError e) { if (!(e.getCause() instanceof ClassNotFoundException)) { throw e; @@ -317,6 +321,8 @@ NamedLocationIdentity.getArrayLocation(JavaKind.Byte)); registerForeignCall(DECRYPT, c.cipherBlockChainingDecryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.getArrayLocation(JavaKind.Byte)); + registerForeignCall(DECRYPT_WITH_ORIGINAL_KEY, c.cipherBlockChainingDecryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, + NamedLocationIdentity.getArrayLocation(JavaKind.Byte)); } catch (JVMCIError e) { if (!(e.getCause() instanceof ClassNotFoundException)) { throw e;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java Mon Nov 16 14:22:56 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java Tue Nov 17 01:58:18 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.replacements; import static com.oracle.graal.hotspot.HotSpotBackend.DECRYPT_BLOCK; +import static com.oracle.graal.hotspot.HotSpotBackend.DECRYPT_BLOCK_WITH_ORIGINAL_KEY; import static com.oracle.graal.hotspot.HotSpotBackend.ENCRYPT_BLOCK; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.probability; @@ -56,6 +57,7 @@ public class AESCryptSubstitutions { static final long kOffset; + static final long lastKeyOffset; static final Class<?> AESCryptClass; static final int AES_BLOCK_SIZE; @@ -66,6 +68,7 @@ ClassLoader cl = Launcher.getLauncher().getClassLoader(); AESCryptClass = Class.forName("com.sun.crypto.provider.AESCrypt", true, cl); kOffset = UnsafeAccess.UNSAFE.objectFieldOffset(AESCryptClass.getDeclaredField("K")); + lastKeyOffset = UnsafeAccess.UNSAFE.objectFieldOffset(AESCryptClass.getDeclaredField("lastKey")); Field aesBlockSizeField = Class.forName("com.sun.crypto.provider.AESConstants", true, cl).getDeclaredField("AES_BLOCK_SIZE"); aesBlockSizeField.setAccessible(true); AES_BLOCK_SIZE = aesBlockSizeField.getInt(null); @@ -75,32 +78,53 @@ } static void encryptBlock(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset) { - crypt(rcvr, in, inOffset, out, outOffset, true); + crypt(rcvr, in, inOffset, out, outOffset, true, false); } static void implEncryptBlock(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset) { - crypt(rcvr, in, inOffset, out, outOffset, true); + crypt(rcvr, in, inOffset, out, outOffset, true, false); } static void decryptBlock(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset) { - crypt(rcvr, in, inOffset, out, outOffset, false); + crypt(rcvr, in, inOffset, out, outOffset, false, false); } static void implDecryptBlock(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset) { - crypt(rcvr, in, inOffset, out, outOffset, false); + crypt(rcvr, in, inOffset, out, outOffset, false, false); } - private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt) { + /** + * Variation for platforms (e.g. SPARC) that need do key expansion in stubs due to compatibility + * issues between Java key expansion and hardware crypto instructions. + */ + static void decryptBlockWithOriginalKey(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset) { + crypt(rcvr, in, inOffset, out, outOffset, false, true); + } + + /** + * @see #decryptBlockWithOriginalKey(Object, byte[], int, byte[], int) + */ + static void implDecryptBlockWithOriginalKey(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset) { + crypt(rcvr, in, inOffset, out, outOffset, false, true); + } + + private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt, boolean withOriginalKey) { checkArgs(in, inOffset, out, outOffset); Object realReceiver = PiNode.piCastNonNull(rcvr, AESCryptClass); Object kObject = UnsafeLoadNode.load(realReceiver, kOffset, JavaKind.Object, LocationIdentity.any()); - Pointer kAddr = Word.objectToTrackedPointer(kObject).add(getArrayBaseOffset(JavaKind.Byte)); + Pointer kAddr = Word.objectToTrackedPointer(kObject).add(getArrayBaseOffset(JavaKind.Int)); Word inAddr = Word.unsigned(ComputeObjectAddressNode.get(in, getArrayBaseOffset(JavaKind.Byte) + inOffset)); Word outAddr = Word.unsigned(ComputeObjectAddressNode.get(out, getArrayBaseOffset(JavaKind.Byte) + outOffset)); if (encrypt) { encryptBlockStub(ENCRYPT_BLOCK, inAddr, outAddr, kAddr); } else { - decryptBlockStub(DECRYPT_BLOCK, inAddr, outAddr, kAddr); + if (withOriginalKey) { + Object lastKeyObject = UnsafeLoadNode.load(realReceiver, lastKeyOffset, JavaKind.Object, LocationIdentity.any()); + Pointer lastKeyAddr = Word.objectToTrackedPointer(lastKeyObject).add(getArrayBaseOffset(JavaKind.Byte)); + decryptBlockWithOriginalKeyStub(DECRYPT_BLOCK_WITH_ORIGINAL_KEY, inAddr, outAddr, kAddr, lastKeyAddr); + } else { + decryptBlockStub(DECRYPT_BLOCK, inAddr, outAddr, kAddr); + } } } @@ -118,4 +142,7 @@ @NodeIntrinsic(ForeignCallNode.class) public static native void decryptBlockStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Pointer key); + + @NodeIntrinsic(ForeignCallNode.class) + public static native void decryptBlockWithOriginalKeyStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Pointer key, Pointer originalKey); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Mon Nov 16 14:22:56 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Tue Nov 17 01:58:18 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.replacements; import static com.oracle.graal.hotspot.HotSpotBackend.DECRYPT; +import static com.oracle.graal.hotspot.HotSpotBackend.DECRYPT_WITH_ORIGINAL_KEY; import static com.oracle.graal.hotspot.HotSpotBackend.ENCRYPT; import static com.oracle.graal.hotspot.replacements.UnsafeAccess.UNSAFE; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; @@ -79,7 +80,7 @@ Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = PiNode.piCastNonNull(embeddedCipher, AESCryptSubstitutions.AESCryptClass); - crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true); + crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false); return inLength; } else { return encrypt(realReceiver, in, inOffset, inLength, out, outOffset); @@ -91,7 +92,7 @@ Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = PiNode.piCastNonNull(embeddedCipher, AESCryptSubstitutions.AESCryptClass); - crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true); + crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false); return inLength; } else { return implEncrypt(realReceiver, in, inOffset, inLength, out, outOffset); @@ -103,7 +104,7 @@ Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = PiNode.piCastNonNull(embeddedCipher, AESCryptSubstitutions.AESCryptClass); - crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false); + crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false); return inLength; } else { return decrypt(realReceiver, in, inOffset, inLength, out, outOffset); @@ -115,26 +116,64 @@ Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = PiNode.piCastNonNull(embeddedCipher, AESCryptSubstitutions.AESCryptClass); - crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false); + crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false); return inLength; } else { return implDecrypt(realReceiver, in, inOffset, inLength, out, outOffset); } } - private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt) { + /** + * Variation for platforms (e.g. SPARC) that need do key expansion in stubs due to compatibility + * issues between Java key expansion and hardware crypto instructions. + */ + static int decryptWithOriginalKey(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { + Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); + Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { + Object aesCipher = PiNode.piCastNonNull(embeddedCipher, AESCryptSubstitutions.AESCryptClass); + crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true); + return inLength; + } else { + return decryptWithOriginalKey(realReceiver, in, inOffset, inLength, out, outOffset); + } + } + + /** + * @see #decryptWithOriginalKey(Object, byte[], int, int, byte[], int) + */ + static int implDecryptWithOriginalKey(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { + Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); + Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { + Object aesCipher = PiNode.piCastNonNull(embeddedCipher, AESCryptSubstitutions.AESCryptClass); + crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true); + return inLength; + } else { + return implDecryptWithOriginalKey(realReceiver, in, inOffset, inLength, out, outOffset); + } + } + + private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt, boolean withOriginalKey) { AESCryptSubstitutions.checkArgs(in, inOffset, out, outOffset); Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object kObject = UnsafeLoadNode.load(embeddedCipher, AESCryptSubstitutions.kOffset, JavaKind.Object, LocationIdentity.any()); + Object aesCipher = PiNode.piCastNonNull(embeddedCipher, AESCryptSubstitutions.AESCryptClass); + Object kObject = UnsafeLoadNode.load(aesCipher, AESCryptSubstitutions.kOffset, JavaKind.Object, LocationIdentity.any()); Object rObject = UnsafeLoadNode.load(realReceiver, rOffset, JavaKind.Object, LocationIdentity.any()); - Pointer kAddr = Word.objectToTrackedPointer(kObject).add(getArrayBaseOffset(JavaKind.Byte)); + Pointer kAddr = Word.objectToTrackedPointer(kObject).add(getArrayBaseOffset(JavaKind.Int)); Pointer rAddr = Word.objectToTrackedPointer(rObject).add(getArrayBaseOffset(JavaKind.Byte)); Word inAddr = Word.unsigned(ComputeObjectAddressNode.get(in, getArrayBaseOffset(JavaKind.Byte) + inOffset)); Word outAddr = Word.unsigned(ComputeObjectAddressNode.get(out, getArrayBaseOffset(JavaKind.Byte) + outOffset)); if (encrypt) { encryptAESCryptStub(ENCRYPT, inAddr, outAddr, kAddr, rAddr, inLength); } else { - decryptAESCryptStub(DECRYPT, inAddr, outAddr, kAddr, rAddr, inLength); + if (withOriginalKey) { + Object lastKeyObject = UnsafeLoadNode.load(aesCipher, AESCryptSubstitutions.lastKeyOffset, JavaKind.Object, LocationIdentity.any()); + Pointer lastKeyAddr = Word.objectToTrackedPointer(lastKeyObject).add(getArrayBaseOffset(JavaKind.Byte)); + decryptAESCryptWithOriginalKeyStub(DECRYPT_WITH_ORIGINAL_KEY, inAddr, outAddr, kAddr, rAddr, inLength, lastKeyAddr); + } else { + decryptAESCryptStub(DECRYPT, inAddr, outAddr, kAddr, rAddr, inLength); + } } } @@ -143,4 +182,7 @@ @NodeIntrinsic(ForeignCallNode.class) public static native void decryptAESCryptStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Pointer key, Pointer r, int inLength); + + @NodeIntrinsic(ForeignCallNode.class) + public static native void decryptAESCryptWithOriginalKeyStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Pointer key, Pointer r, int inLength, Pointer originalKey); }