Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/javax/crypto/CipherSpi/CipherByteBufferOverwriteTest.java
41152 views
1
/*
2
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/**
25
* @test
26
* @bug 8181386
27
* @summary CipherSpi ByteBuffer to byte array conversion fails for
28
* certain data overlap conditions
29
* @run main CipherByteBufferOverwriteTest AES/CBC/PKCS5Padding 0 false
30
* @run main CipherByteBufferOverwriteTest AES/CBC/PKCS5Padding 0 true
31
* @run main CipherByteBufferOverwriteTest AES/CBC/PKCS5Padding 4 false
32
* @run main CipherByteBufferOverwriteTest AES/CBC/PKCS5Padding 4 true
33
* @run main CipherByteBufferOverwriteTest AES/GCM/NoPadding 0 false
34
* @run main CipherByteBufferOverwriteTest AES/GCM/NoPadding 0 true
35
* @run main CipherByteBufferOverwriteTest AES/GCM/NoPadding 4 false
36
* @run main CipherByteBufferOverwriteTest AES/GCM/NoPadding 4 true
37
*/
38
39
import java.math.BigInteger;
40
import java.security.spec.AlgorithmParameterSpec;
41
import javax.crypto.Cipher;
42
import javax.crypto.SecretKey;
43
import javax.crypto.spec.GCMParameterSpec;
44
import javax.crypto.spec.IvParameterSpec;
45
import javax.crypto.spec.SecretKeySpec;
46
import java.nio.ByteBuffer;
47
import java.util.Arrays;
48
49
public class CipherByteBufferOverwriteTest {
50
51
private static final boolean DEBUG = false;
52
53
private static String transformation;
54
55
// must be larger than the temp array size, i.e. 4096, hardcoded in
56
// javax.crypto.CipherSpi class
57
private static final int PLAINTEXT_SIZE = 8192;
58
// leave room for padding
59
private static final int CIPHERTEXT_BUFFER_SIZE = PLAINTEXT_SIZE + 32;
60
61
private static final SecretKey KEY = new SecretKeySpec(new byte[16], "AES");
62
private static AlgorithmParameterSpec params;
63
64
private static ByteBuffer inBuf;
65
private static ByteBuffer outBuf;
66
67
private enum BufferType {
68
ALLOCATE, DIRECT, WRAP;
69
}
70
71
public static void main(String[] args) throws Exception {
72
73
transformation = args[0];
74
int offset = Integer.parseInt(args[1]);
75
boolean useRO = Boolean.parseBoolean(args[2]);
76
77
if (transformation.equalsIgnoreCase("AES/GCM/NoPadding")) {
78
params = new GCMParameterSpec(16 * 8, new byte[16]);
79
} else {
80
params = new IvParameterSpec(new byte[16]);
81
}
82
// an all-zeros plaintext is the easiest way to demonstrate the issue,
83
// but it fails with any plaintext, of course
84
byte[] expectedPT = new byte[PLAINTEXT_SIZE];
85
byte[] buf = new byte[offset + CIPHERTEXT_BUFFER_SIZE];
86
System.arraycopy(expectedPT, 0, buf, 0, PLAINTEXT_SIZE);
87
88
// generate expected cipher text using byte[] methods
89
Cipher c = Cipher.getInstance(transformation);
90
c.init(Cipher.ENCRYPT_MODE, KEY, params);
91
byte[] expectedCT = c.doFinal(expectedPT);
92
93
// Test#1: against ByteBuffer generated with allocate(int) call
94
prepareBuffers(BufferType.ALLOCATE, useRO, buf.length,
95
buf, 0, PLAINTEXT_SIZE, offset);
96
97
runTest(offset, expectedPT, expectedCT);
98
System.out.println("\tALLOCATE: passed");
99
100
// Test#2: against direct ByteBuffer
101
prepareBuffers(BufferType.DIRECT, useRO, buf.length,
102
buf, 0, PLAINTEXT_SIZE, offset);
103
104
runTest(offset, expectedPT, expectedCT);
105
System.out.println("\tDIRECT: passed");
106
107
// Test#3: against ByteBuffer wrapping existing array
108
prepareBuffers(BufferType.WRAP, useRO, buf.length,
109
buf, 0, PLAINTEXT_SIZE, offset);
110
111
runTest(offset, expectedPT, expectedCT);
112
System.out.println("\tWRAP: passed");
113
114
System.out.println("All Tests Passed");
115
}
116
117
private static void prepareBuffers(BufferType type,
118
boolean useRO, int bufSz, byte[] in, int inOfs, int inLen,
119
int outOfs) {
120
switch (type) {
121
case ALLOCATE:
122
outBuf = ByteBuffer.allocate(bufSz);
123
inBuf = outBuf.slice();
124
inBuf.put(in, inOfs, inLen);
125
inBuf.rewind();
126
inBuf.limit(inLen);
127
outBuf.position(outOfs);
128
break;
129
case DIRECT:
130
outBuf = ByteBuffer.allocateDirect(bufSz);
131
inBuf = outBuf.slice();
132
inBuf.put(in, inOfs, inLen);
133
inBuf.rewind();
134
inBuf.limit(inLen);
135
outBuf.position(outOfs);
136
break;
137
case WRAP:
138
if (in.length < bufSz) {
139
throw new RuntimeException("ERROR: Input buffer too small");
140
}
141
outBuf = ByteBuffer.wrap(in);
142
inBuf = ByteBuffer.wrap(in, inOfs, inLen);
143
outBuf.position(outOfs);
144
break;
145
}
146
if (useRO) {
147
inBuf = inBuf.asReadOnlyBuffer();
148
}
149
if (DEBUG) {
150
System.out.println("inBuf, pos = " + inBuf.position() +
151
", capacity = " + inBuf.capacity() +
152
", limit = " + inBuf.limit() +
153
", remaining = " + inBuf.remaining());
154
System.out.println("outBuf, pos = " + outBuf.position() +
155
", capacity = " + outBuf.capacity() +
156
", limit = " + outBuf.limit() +
157
", remaining = " + outBuf.remaining());
158
}
159
}
160
161
private static void runTest(int ofs, byte[] expectedPT, byte[] expectedCT)
162
throws Exception {
163
164
Cipher c = Cipher.getInstance(transformation);
165
c.init(Cipher.ENCRYPT_MODE, KEY, params);
166
int ciphertextSize = c.doFinal(inBuf, outBuf);
167
168
// read out the encrypted result
169
outBuf.position(ofs);
170
byte[] finalCT = new byte[ciphertextSize];
171
if (DEBUG) {
172
System.out.println("runTest, ciphertextSize = " + ciphertextSize);
173
System.out.println("runTest, ofs = " + ofs +
174
", remaining = " + finalCT.length +
175
", limit = " + outBuf.limit());
176
}
177
outBuf.get(finalCT);
178
179
if (!Arrays.equals(finalCT, expectedCT)) {
180
System.err.println("Ciphertext mismatch:" +
181
"\nresult (len=" + finalCT.length + "):\n" +
182
String.format("%0" + (finalCT.length << 1) + "x",
183
new BigInteger(1, finalCT)) +
184
"\nexpected (len=" + expectedCT.length + "):\n" +
185
String.format("%0" + (expectedCT.length << 1) + "x",
186
new BigInteger(1, expectedCT)));
187
throw new Exception("ERROR: Ciphertext does not match");
188
}
189
190
// now do decryption
191
outBuf.position(ofs);
192
outBuf.limit(ofs + ciphertextSize);
193
c.init(Cipher.DECRYPT_MODE, KEY, params);
194
ByteBuffer finalPTBuf = ByteBuffer.allocate(
195
c.getOutputSize(outBuf.remaining()));
196
c.doFinal(outBuf, finalPTBuf);
197
198
// read out the decrypted result
199
finalPTBuf.flip();
200
byte[] finalPT = new byte[finalPTBuf.remaining()];
201
finalPTBuf.get(finalPT);
202
203
if (!Arrays.equals(finalPT, expectedPT)) {
204
System.err.println("Ciphertext mismatch " +
205
"):\nresult (len=" + finalCT.length + "):\n" +
206
String.format("%0" + (finalCT.length << 1) + "x",
207
new BigInteger(1, finalCT)) +
208
"\nexpected (len=" + expectedCT.length + "):\n" +
209
String.format("%0" + (expectedCT.length << 1) + "x",
210
new BigInteger(1, expectedCT)));
211
throw new Exception("ERROR: Plaintext does not match");
212
}
213
}
214
}
215
216
217