001/* 002 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.hotspot.replacements; 024 025import static com.oracle.graal.hotspot.HotSpotBackend.*; 026import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; 027import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; 028import static com.oracle.graal.word.Word.*; 029 030import java.lang.reflect.*; 031 032import jdk.internal.jvmci.common.*; 033import jdk.internal.jvmci.meta.*; 034import sun.misc.*; 035 036import com.oracle.graal.compiler.common.spi.*; 037import com.oracle.graal.graph.Node.ConstantNodeParameter; 038import com.oracle.graal.graph.Node.NodeIntrinsic; 039import com.oracle.graal.hotspot.nodes.*; 040import com.oracle.graal.nodes.*; 041import com.oracle.graal.nodes.extended.*; 042import com.oracle.graal.word.*; 043 044// JaCoCo Exclude 045 046/** 047 * Substitutions for {@code com.sun.crypto.provider.AESCrypt} methods. 048 */ 049public class AESCryptSubstitutions { 050 051 static final long kOffset; 052 static final Class<?> AESCryptClass; 053 static final int AES_BLOCK_SIZE; 054 055 static { 056 try { 057 // Need to use launcher class path as com.sun.crypto.provider.AESCrypt 058 // is normally not on the boot class path 059 ClassLoader cl = Launcher.getLauncher().getClassLoader(); 060 AESCryptClass = Class.forName("com.sun.crypto.provider.AESCrypt", true, cl); 061 kOffset = UnsafeAccess.unsafe.objectFieldOffset(AESCryptClass.getDeclaredField("K")); 062 Field aesBlockSizeField = Class.forName("com.sun.crypto.provider.AESConstants", true, cl).getDeclaredField("AES_BLOCK_SIZE"); 063 aesBlockSizeField.setAccessible(true); 064 AES_BLOCK_SIZE = aesBlockSizeField.getInt(null); 065 } catch (Exception ex) { 066 throw new JVMCIError(ex); 067 } 068 } 069 070 static void encryptBlock(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset) { 071 crypt(rcvr, in, inOffset, out, outOffset, true); 072 } 073 074 static void decryptBlock(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset) { 075 crypt(rcvr, in, inOffset, out, outOffset, false); 076 } 077 078 private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt) { 079 checkArgs(in, inOffset, out, outOffset); 080 Object realReceiver = PiNode.piCastNonNull(rcvr, AESCryptClass); 081 Object kObject = UnsafeLoadNode.load(realReceiver, kOffset, Kind.Object, LocationIdentity.any()); 082 Word kAddr = fromWordBase(Word.fromObject(kObject).add(arrayBaseOffset(Kind.Byte))); 083 Word inAddr = Word.unsigned(ComputeObjectAddressNode.get(in, arrayBaseOffset(Kind.Byte) + inOffset)); 084 Word outAddr = Word.unsigned(ComputeObjectAddressNode.get(out, arrayBaseOffset(Kind.Byte) + outOffset)); 085 if (encrypt) { 086 encryptBlockStub(ENCRYPT_BLOCK, inAddr, outAddr, kAddr); 087 } else { 088 decryptBlockStub(DECRYPT_BLOCK, inAddr, outAddr, kAddr); 089 } 090 } 091 092 /** 093 * Perform null and array bounds checks for arguments to a cipher operation. 094 */ 095 static void checkArgs(byte[] in, int inOffset, byte[] out, int outOffset) { 096 if (probability(VERY_SLOW_PATH_PROBABILITY, inOffset < 0 || in.length - AES_BLOCK_SIZE < inOffset || outOffset < 0 || out.length - AES_BLOCK_SIZE < outOffset)) { 097 DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); 098 } 099 } 100 101 @NodeIntrinsic(ForeignCallNode.class) 102 public static native void encryptBlockStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Word key); 103 104 @NodeIntrinsic(ForeignCallNode.class) 105 public static native void decryptBlockStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Word key); 106}