22 */
23 package org.graalvm.compiler.hotspot.replacements;
24
25 import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT;
26 import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_WITH_ORIGINAL_KEY;
27 import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT;
28 import static org.graalvm.compiler.hotspot.replacements.UnsafeAccess.UNSAFE;
29 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
30
31 import org.graalvm.compiler.api.replacements.ClassSubstitution;
32 import org.graalvm.compiler.api.replacements.Fold;
33 import org.graalvm.compiler.api.replacements.MethodSubstitution;
34 import org.graalvm.compiler.core.common.LocationIdentity;
35 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
36 import org.graalvm.compiler.debug.GraalError;
37 import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
38 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
39 import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode;
40 import org.graalvm.compiler.nodes.PiNode;
41 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
42 import org.graalvm.compiler.nodes.extended.UnsafeLoadNode;
43 import org.graalvm.compiler.word.Pointer;
44 import org.graalvm.compiler.word.Word;
45
46 import jdk.vm.ci.meta.JavaKind;
47
48 // JaCoCo Exclude
49
50 /**
51 * Substitutions for {@code com.sun.crypto.provider.CipherBlockChaining} methods.
52 */
53 @ClassSubstitution(className = "com.sun.crypto.provider.CipherBlockChaining", optional = true)
54 public class CipherBlockChainingSubstitutions {
55
56 private static final long embeddedCipherOffset;
57 private static final long rOffset;
58 private static final Class<?> cipherBlockChainingClass;
59 private static final Class<?> feedbackCipherClass;
60 static {
61 try {
62 // Need to use the system class loader as com.sun.crypto.provider.FeedbackCipher
65 ClassLoader cl = ClassLoader.getSystemClassLoader();
66
67 feedbackCipherClass = Class.forName("com.sun.crypto.provider.FeedbackCipher", true, cl);
68 embeddedCipherOffset = UNSAFE.objectFieldOffset(feedbackCipherClass.getDeclaredField("embeddedCipher"));
69
70 cipherBlockChainingClass = Class.forName("com.sun.crypto.provider.CipherBlockChaining", true, cl);
71 rOffset = UNSAFE.objectFieldOffset(cipherBlockChainingClass.getDeclaredField("r"));
72 } catch (Exception ex) {
73 throw new GraalError(ex);
74 }
75 }
76
77 @Fold
78 static Class<?> getAESCryptClass() {
79 return AESCryptSubstitutions.AESCryptClass;
80 }
81
82 @MethodSubstitution(isStatic = false)
83 static int encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
84 Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
85 Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
86 if (getAESCryptClass().isInstance(embeddedCipher)) {
87 Object aesCipher = getAESCryptClass().cast(embeddedCipher);
88 crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false);
89 return inLength;
90 } else {
91 return encrypt(realReceiver, in, inOffset, inLength, out, outOffset);
92 }
93 }
94
95 @MethodSubstitution(isStatic = false, value = "implEncrypt")
96 static int implEncrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
97 Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
98 Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
99 if (getAESCryptClass().isInstance(embeddedCipher)) {
100 Object aesCipher = getAESCryptClass().cast(embeddedCipher);
101 crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false);
102 return inLength;
103 } else {
104 return implEncrypt(realReceiver, in, inOffset, inLength, out, outOffset);
105 }
106 }
107
108 @MethodSubstitution(isStatic = false)
109 static int decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
110 Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
111 Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
112 if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
113 Object aesCipher = getAESCryptClass().cast(embeddedCipher);
114 crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false);
115 return inLength;
116 } else {
117 return decrypt(realReceiver, in, inOffset, inLength, out, outOffset);
118 }
119 }
120
121 @MethodSubstitution(isStatic = false)
122 static int implDecrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
123 Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
124 Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
125 if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
126 Object aesCipher = getAESCryptClass().cast(embeddedCipher);
127 crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false);
128 return inLength;
129 } else {
130 return implDecrypt(realReceiver, in, inOffset, inLength, out, outOffset);
131 }
132 }
133
134 /**
135 * Variation for platforms (e.g. SPARC) that need do key expansion in stubs due to compatibility
136 * issues between Java key expansion and hardware crypto instructions.
137 */
138 @MethodSubstitution(isStatic = false, value = "decrypt")
139 static int decryptWithOriginalKey(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
140 Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
141 Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
142 if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
143 Object aesCipher = getAESCryptClass().cast(embeddedCipher);
144 crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true);
145 return inLength;
146 } else {
147 return decryptWithOriginalKey(realReceiver, in, inOffset, inLength, out, outOffset);
148 }
149 }
150
151 /**
152 * @see #decryptWithOriginalKey(Object, byte[], int, int, byte[], int)
153 */
154 @MethodSubstitution(isStatic = false, value = "implDecrypt")
155 static int implDecryptWithOriginalKey(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
156 Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
157 Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
158 if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
159 Object aesCipher = getAESCryptClass().cast(embeddedCipher);
160 crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true);
161 return inLength;
162 } else {
163 return implDecryptWithOriginalKey(realReceiver, in, inOffset, inLength, out, outOffset);
164 }
165 }
166
167 private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt, boolean withOriginalKey) {
168 AESCryptSubstitutions.checkArgs(in, inOffset, out, outOffset);
169 Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
170 Object aesCipher = getAESCryptClass().cast(embeddedCipher);
171 Object kObject = UnsafeLoadNode.load(aesCipher, AESCryptSubstitutions.kOffset, JavaKind.Object, LocationIdentity.any());
172 Object rObject = UnsafeLoadNode.load(realReceiver, rOffset, JavaKind.Object, LocationIdentity.any());
173 Pointer kAddr = Word.objectToTrackedPointer(kObject).add(getArrayBaseOffset(JavaKind.Int));
174 Pointer rAddr = Word.objectToTrackedPointer(rObject).add(getArrayBaseOffset(JavaKind.Byte));
175 Word inAddr = Word.unsigned(ComputeObjectAddressNode.get(in, getArrayBaseOffset(JavaKind.Byte) + inOffset));
176 Word outAddr = Word.unsigned(ComputeObjectAddressNode.get(out, getArrayBaseOffset(JavaKind.Byte) + outOffset));
177 if (encrypt) {
178 encryptAESCryptStub(ENCRYPT, inAddr, outAddr, kAddr, rAddr, inLength);
179 } else {
180 if (withOriginalKey) {
181 Object lastKeyObject = UnsafeLoadNode.load(aesCipher, AESCryptSubstitutions.lastKeyOffset, JavaKind.Object, LocationIdentity.any());
182 Pointer lastKeyAddr = Word.objectToTrackedPointer(lastKeyObject).add(getArrayBaseOffset(JavaKind.Byte));
183 decryptAESCryptWithOriginalKeyStub(DECRYPT_WITH_ORIGINAL_KEY, inAddr, outAddr, kAddr, rAddr, inLength, lastKeyAddr);
184 } else {
185 decryptAESCryptStub(DECRYPT, inAddr, outAddr, kAddr, rAddr, inLength);
186 }
187 }
188 }
189
190 @NodeIntrinsic(ForeignCallNode.class)
191 public static native void encryptAESCryptStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Pointer key, Pointer r, int inLength);
192
193 @NodeIntrinsic(ForeignCallNode.class)
194 public static native void decryptAESCryptStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Pointer key, Pointer r, int inLength);
195
196 @NodeIntrinsic(ForeignCallNode.class)
197 public static native void decryptAESCryptWithOriginalKeyStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Pointer key, Pointer r, int inLength, Pointer originalKey);
198 }
|
22 */
23 package org.graalvm.compiler.hotspot.replacements;
24
25 import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT;
26 import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_WITH_ORIGINAL_KEY;
27 import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT;
28 import static org.graalvm.compiler.hotspot.replacements.UnsafeAccess.UNSAFE;
29 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
30
31 import org.graalvm.compiler.api.replacements.ClassSubstitution;
32 import org.graalvm.compiler.api.replacements.Fold;
33 import org.graalvm.compiler.api.replacements.MethodSubstitution;
34 import org.graalvm.compiler.core.common.LocationIdentity;
35 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
36 import org.graalvm.compiler.debug.GraalError;
37 import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
38 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
39 import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode;
40 import org.graalvm.compiler.nodes.PiNode;
41 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
42 import org.graalvm.compiler.nodes.extended.RawLoadNode;
43 import org.graalvm.compiler.word.Pointer;
44 import org.graalvm.compiler.word.Word;
45
46 import jdk.vm.ci.meta.JavaKind;
47
48 // JaCoCo Exclude
49
50 /**
51 * Substitutions for {@code com.sun.crypto.provider.CipherBlockChaining} methods.
52 */
53 @ClassSubstitution(className = "com.sun.crypto.provider.CipherBlockChaining", optional = true)
54 public class CipherBlockChainingSubstitutions {
55
56 private static final long embeddedCipherOffset;
57 private static final long rOffset;
58 private static final Class<?> cipherBlockChainingClass;
59 private static final Class<?> feedbackCipherClass;
60 static {
61 try {
62 // Need to use the system class loader as com.sun.crypto.provider.FeedbackCipher
65 ClassLoader cl = ClassLoader.getSystemClassLoader();
66
67 feedbackCipherClass = Class.forName("com.sun.crypto.provider.FeedbackCipher", true, cl);
68 embeddedCipherOffset = UNSAFE.objectFieldOffset(feedbackCipherClass.getDeclaredField("embeddedCipher"));
69
70 cipherBlockChainingClass = Class.forName("com.sun.crypto.provider.CipherBlockChaining", true, cl);
71 rOffset = UNSAFE.objectFieldOffset(cipherBlockChainingClass.getDeclaredField("r"));
72 } catch (Exception ex) {
73 throw new GraalError(ex);
74 }
75 }
76
77 @Fold
78 static Class<?> getAESCryptClass() {
79 return AESCryptSubstitutions.AESCryptClass;
80 }
81
82 @MethodSubstitution(isStatic = false)
83 static int encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
84 Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
85 Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
86 if (getAESCryptClass().isInstance(embeddedCipher)) {
87 Object aesCipher = getAESCryptClass().cast(embeddedCipher);
88 crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false);
89 return inLength;
90 } else {
91 return encrypt(realReceiver, in, inOffset, inLength, out, outOffset);
92 }
93 }
94
95 @MethodSubstitution(isStatic = false, value = "implEncrypt")
96 static int implEncrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
97 Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
98 Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
99 if (getAESCryptClass().isInstance(embeddedCipher)) {
100 Object aesCipher = getAESCryptClass().cast(embeddedCipher);
101 crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false);
102 return inLength;
103 } else {
104 return implEncrypt(realReceiver, in, inOffset, inLength, out, outOffset);
105 }
106 }
107
108 @MethodSubstitution(isStatic = false)
109 static int decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
110 Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
111 Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
112 if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
113 Object aesCipher = getAESCryptClass().cast(embeddedCipher);
114 crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false);
115 return inLength;
116 } else {
117 return decrypt(realReceiver, in, inOffset, inLength, out, outOffset);
118 }
119 }
120
121 @MethodSubstitution(isStatic = false)
122 static int implDecrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
123 Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
124 Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
125 if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
126 Object aesCipher = getAESCryptClass().cast(embeddedCipher);
127 crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false);
128 return inLength;
129 } else {
130 return implDecrypt(realReceiver, in, inOffset, inLength, out, outOffset);
131 }
132 }
133
134 /**
135 * Variation for platforms (e.g. SPARC) that need do key expansion in stubs due to compatibility
136 * issues between Java key expansion and hardware crypto instructions.
137 */
138 @MethodSubstitution(isStatic = false, value = "decrypt")
139 static int decryptWithOriginalKey(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
140 Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
141 Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
142 if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
143 Object aesCipher = getAESCryptClass().cast(embeddedCipher);
144 crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true);
145 return inLength;
146 } else {
147 return decryptWithOriginalKey(realReceiver, in, inOffset, inLength, out, outOffset);
148 }
149 }
150
151 /**
152 * @see #decryptWithOriginalKey(Object, byte[], int, int, byte[], int)
153 */
154 @MethodSubstitution(isStatic = false, value = "implDecrypt")
155 static int implDecryptWithOriginalKey(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
156 Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
157 Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any());
158 if (in != out && getAESCryptClass().isInstance(embeddedCipher)) {
159 Object aesCipher = getAESCryptClass().cast(embeddedCipher);
160 crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true);
161 return inLength;
162 } else {
163 return implDecryptWithOriginalKey(realReceiver, in, inOffset, inLength, out, outOffset);
164 }
165 }
166
167 private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt, boolean withOriginalKey) {
168 AESCryptSubstitutions.checkArgs(in, inOffset, out, outOffset);
169 Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
170 Object aesCipher = getAESCryptClass().cast(embeddedCipher);
171 Object kObject = RawLoadNode.load(aesCipher, AESCryptSubstitutions.kOffset, JavaKind.Object, LocationIdentity.any());
172 Object rObject = RawLoadNode.load(realReceiver, rOffset, JavaKind.Object, LocationIdentity.any());
173 Pointer kAddr = Word.objectToTrackedPointer(kObject).add(getArrayBaseOffset(JavaKind.Int));
174 Pointer rAddr = Word.objectToTrackedPointer(rObject).add(getArrayBaseOffset(JavaKind.Byte));
175 Word inAddr = Word.unsigned(ComputeObjectAddressNode.get(in, getArrayBaseOffset(JavaKind.Byte) + inOffset));
176 Word outAddr = Word.unsigned(ComputeObjectAddressNode.get(out, getArrayBaseOffset(JavaKind.Byte) + outOffset));
177 if (encrypt) {
178 encryptAESCryptStub(ENCRYPT, inAddr, outAddr, kAddr, rAddr, inLength);
179 } else {
180 if (withOriginalKey) {
181 Object lastKeyObject = RawLoadNode.load(aesCipher, AESCryptSubstitutions.lastKeyOffset, JavaKind.Object, LocationIdentity.any());
182 Pointer lastKeyAddr = Word.objectToTrackedPointer(lastKeyObject).add(getArrayBaseOffset(JavaKind.Byte));
183 decryptAESCryptWithOriginalKeyStub(DECRYPT_WITH_ORIGINAL_KEY, inAddr, outAddr, kAddr, rAddr, inLength, lastKeyAddr);
184 } else {
185 decryptAESCryptStub(DECRYPT, inAddr, outAddr, kAddr, rAddr, inLength);
186 }
187 }
188 }
189
190 @NodeIntrinsic(ForeignCallNode.class)
191 public static native void encryptAESCryptStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Pointer key, Pointer r, int inLength);
192
193 @NodeIntrinsic(ForeignCallNode.class)
194 public static native void decryptAESCryptStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Pointer key, Pointer r, int inLength);
195
196 @NodeIntrinsic(ForeignCallNode.class)
197 public static native void decryptAESCryptWithOriginalKeyStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word in, Word out, Pointer key, Pointer r, int inLength, Pointer originalKey);
198 }
|