Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/com/sun/crypto/provider/Cipher/AEAD/SameBuffer.java
41161 views
1
/*
2
* Copyright (c) 2007, 2021, 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
import java.nio.ByteBuffer;
25
import java.security.AlgorithmParameters;
26
import java.security.Provider;
27
import java.security.Security;
28
import java.util.HexFormat;
29
import javax.crypto.SecretKey;
30
import javax.crypto.Cipher;
31
import javax.crypto.KeyGenerator;
32
import javax.crypto.spec.GCMParameterSpec;
33
import jdk.test.lib.Convert;
34
35
/*
36
* @test
37
* @bug 8048596
38
* @summary Check if AEAD operations work correctly when buffers used
39
* for storing plain text and cipher text are overlapped or the same
40
* @library /test/lib
41
*/
42
public class SameBuffer {
43
44
private static final String PROVIDER = "SunJCE";
45
private static final String AES = "AES";
46
private static final String GCM = "GCM";
47
private static final String PADDING = "NoPadding";
48
private static final int OFFSET = 2;
49
private static final int OFFSETS = 4;
50
private static final int KEY_LENGTHS[] = { 128, 192, 256 };
51
private static final int TEXT_LENGTHS[] = { 0, 1024 };
52
private static final int AAD_LENGTHS[] = { 0, 1024 };
53
54
private final Provider provider;
55
private final SecretKey key;
56
private final String transformation;
57
private final int textLength;
58
private final int AADLength;
59
60
/**
61
* Constructor of the test
62
*
63
* @param provider security provider
64
* @param keyStrength key length
65
* @param textLength length of data
66
* @param AADLength AAD length
67
*/
68
public SameBuffer(Provider provider, String algorithm, String mode,
69
String padding, int keyStrength, int textLength, int AADLength)
70
throws Exception {
71
72
// init a secret key
73
KeyGenerator kg = KeyGenerator.getInstance(algorithm, provider);
74
kg.init(keyStrength);
75
key = kg.generateKey();
76
77
this.transformation = algorithm + "/" + mode + "/" + padding;
78
this.provider = provider;
79
this.textLength = textLength;
80
this.AADLength = AADLength;
81
}
82
83
public static void main(String[] args) throws Exception {
84
Provider p = Security.getProvider(PROVIDER);
85
for (int keyLength : KEY_LENGTHS) {
86
for (int textLength : TEXT_LENGTHS) {
87
for (int AADLength : AAD_LENGTHS) {
88
for (int i = 0; i < OFFSETS; i++) {
89
// try different offsets
90
int offset = i * OFFSET;
91
runTest(p, AES, GCM, PADDING, keyLength, textLength,
92
AADLength, offset);
93
}
94
}
95
}
96
}
97
}
98
99
/*
100
* Run single test case with given parameters
101
*/
102
static void runTest(Provider p, String algo, String mode,
103
String padding, int keyLength, int textLength, int AADLength,
104
int offset) throws Exception {
105
System.out.println("Testing " + keyLength + " key length; "
106
+ textLength + " text length; " + AADLength + " AAD length; "
107
+ offset + " offset");
108
if (keyLength > Cipher.getMaxAllowedKeyLength(algo)) {
109
// skip this if this key length is larger than what's
110
// configured in the jce jurisdiction policy files
111
return;
112
}
113
SameBuffer test = new SameBuffer(p, algo, mode,
114
padding, keyLength, textLength, AADLength);
115
116
/*
117
* There are four test cases:
118
* 1. AAD and text are placed in separated byte arrays
119
* 2. AAD and text are placed in the same byte array
120
* 3. AAD and text are placed in separated byte buffers
121
* 4. AAD and text are placed in the same byte buffer
122
*/
123
Cipher ci = test.createCipher(Cipher.ENCRYPT_MODE, null);
124
AlgorithmParameters params = ci.getParameters();
125
test.doTestWithSeparateArrays(offset, params);
126
test.doTestWithSameArrays(offset, params);
127
test.doTestWithSeparatedBuffer(offset, params);
128
test.doTestWithSameBuffer(offset, params);
129
}
130
131
/*
132
* Run the test in case when AAD and text are placed in separated byte
133
* arrays.
134
*/
135
private void doTestWithSeparateArrays(int offset,
136
AlgorithmParameters params) throws Exception {
137
// prepare buffers to test
138
Cipher c = createCipher(Cipher.ENCRYPT_MODE, params);
139
int outputLength = c.getOutputSize(textLength);
140
int outputBufSize = outputLength + offset * 2;
141
142
byte[] inputText = Helper.generateBytes(outputBufSize);
143
byte[] AAD = Helper.generateBytes(AADLength);
144
145
// do the test
146
runGCMWithSeparateArray(Cipher.ENCRYPT_MODE, AAD, inputText, offset * 2,
147
textLength, offset, params);
148
int tagLength = c.getParameters()
149
.getParameterSpec(GCMParameterSpec.class).getTLen() / 8;
150
runGCMWithSeparateArray(Cipher.DECRYPT_MODE, AAD, inputText, offset,
151
textLength + tagLength, offset, params);
152
}
153
154
/**
155
* Run the test in case when AAD and text are placed in the same byte
156
* array.
157
*/
158
private void doTestWithSameArrays(int offset, AlgorithmParameters params)
159
throws Exception {
160
// prepare buffers to test
161
Cipher c = createCipher(Cipher.ENCRYPT_MODE, params);
162
int outputLength = c.getOutputSize(textLength);
163
int outputBufSize = AADLength + outputLength + offset * 2;
164
165
byte[] AAD_and_text = Helper.generateBytes(outputBufSize);
166
167
// do the test
168
runGCMWithSameArray(Cipher.ENCRYPT_MODE, AAD_and_text, AADLength + offset,
169
textLength, params);
170
int tagLength = c.getParameters()
171
.getParameterSpec(GCMParameterSpec.class).getTLen() / 8;
172
runGCMWithSameArray(Cipher.DECRYPT_MODE, AAD_and_text, AADLength + offset,
173
textLength + tagLength, params);
174
}
175
176
/*
177
* Run the test in case when AAD and text are placed in separated ByteBuffer
178
*/
179
private void doTestWithSeparatedBuffer(int offset,
180
AlgorithmParameters params) throws Exception {
181
// prepare AAD byte buffers to test
182
byte[] AAD = Helper.generateBytes(AADLength);
183
ByteBuffer AAD_Buf = ByteBuffer.allocate(AADLength);
184
AAD_Buf.put(AAD, 0, AAD.length);
185
AAD_Buf.flip();
186
187
// prepare text byte buffer to encrypt/decrypt
188
Cipher c = createCipher(Cipher.ENCRYPT_MODE, params);
189
int outputLength = c.getOutputSize(textLength);
190
int outputBufSize = outputLength + offset;
191
byte[] inputText = Helper.generateBytes(outputBufSize);
192
ByteBuffer plainTextBB = ByteBuffer.allocateDirect(inputText.length);
193
plainTextBB.put(inputText);
194
plainTextBB.position(offset);
195
plainTextBB.limit(offset + textLength);
196
197
// do test
198
runGCMWithSeparateBuffers(Cipher.ENCRYPT_MODE, AAD_Buf, plainTextBB, offset,
199
textLength, params);
200
int tagLength = c.getParameters()
201
.getParameterSpec(GCMParameterSpec.class).getTLen() / 8;
202
plainTextBB.position(offset);
203
plainTextBB.limit(offset + textLength + tagLength);
204
runGCMWithSeparateBuffers(Cipher.DECRYPT_MODE, AAD_Buf, plainTextBB, offset,
205
textLength + tagLength, params);
206
}
207
208
/*
209
* Run the test in case when AAD and text are placed in the same ByteBuffer
210
*/
211
private void doTestWithSameBuffer(int offset, AlgorithmParameters params)
212
throws Exception {
213
// calculate output length
214
Cipher c = createCipher(Cipher.ENCRYPT_MODE, params);
215
int outputLength = c.getOutputSize(textLength);
216
217
// prepare byte buffer contained AAD and plain text
218
int bufSize = AADLength + offset + outputLength;
219
byte[] AAD_and_Text = Helper.generateBytes(bufSize);
220
ByteBuffer AAD_and_Text_Buf = ByteBuffer.allocate(bufSize);
221
AAD_and_Text_Buf.put(AAD_and_Text, 0, AAD_and_Text.length);
222
223
// do test
224
runGCMWithSameBuffer(Cipher.ENCRYPT_MODE, AAD_and_Text_Buf, offset,
225
textLength, params);
226
int tagLength = c.getParameters()
227
.getParameterSpec(GCMParameterSpec.class).getTLen() / 8;
228
AAD_and_Text_Buf.limit(AADLength + offset + textLength + tagLength);
229
runGCMWithSameBuffer(Cipher.DECRYPT_MODE, AAD_and_Text_Buf, offset,
230
textLength + tagLength, params);
231
232
}
233
234
/*
235
* Execute GCM encryption/decryption of a text placed in a byte array.
236
* AAD is placed in the separated byte array.
237
* Data are processed twice:
238
* - in a separately allocated buffer
239
* - in the text buffer
240
* Check if two results are equal
241
*/
242
private void runGCMWithSeparateArray(int mode, byte[] AAD, byte[] text,
243
int txtOffset, int length, int offset, AlgorithmParameters params)
244
throws Exception {
245
// first, generate the cipher text at an allocated buffer
246
Cipher cipher = createCipher(mode, params);
247
cipher.updateAAD(AAD);
248
byte[] outputText = cipher.doFinal(text, txtOffset, length);
249
250
// new cipher for encrypt operation
251
Cipher anotherCipher = createCipher(mode, params);
252
anotherCipher.updateAAD(AAD);
253
254
// next, generate cipher text again at the same buffer of plain text
255
int myoff = offset;
256
int off = anotherCipher.update(text, txtOffset, length, text, myoff);
257
anotherCipher.doFinal(text, myoff + off);
258
259
// check if two resutls are equal
260
if (!isEqual(text, myoff, outputText, 0, outputText.length)) {
261
System.err.println(
262
"\noutputText: len = " + outputText.length + " txtOffset = " + txtOffset + "\n" +
263
HexFormat.of().withUpperCase().formatHex(outputText) + "\n" +
264
"text: len = " + text.length + " myoff = " + myoff + "\n" +
265
HexFormat.of().withUpperCase().formatHex(text) + "\n" +
266
"length " + length);
267
System.err.println("tlen = " + params.getParameterSpec(GCMParameterSpec.class).getTLen() / 8);
268
throw new RuntimeException("Two results not equal, mode:" + mode);
269
}
270
}
271
272
/*
273
* Execute GCM encrption/decryption of a text. The AAD and text to process
274
* are placed in the same byte array. Data are processed twice:
275
* - in a separetly allocated buffer
276
* - in a buffer that shares content of the AAD_and_Text_BA
277
* Check if two results are equal
278
*/
279
private void runGCMWithSameArray(int mode, byte[] array, int txtOffset,
280
int length, AlgorithmParameters params) throws Exception {
281
// first, generate cipher text at an allocated buffer
282
Cipher cipher = createCipher(mode, params);
283
cipher.updateAAD(array, 0, AADLength);
284
byte[] outputText = cipher.doFinal(array, txtOffset, length);
285
286
// new cipher for encrypt operation
287
Cipher anotherCipher = createCipher(mode, params);
288
anotherCipher.updateAAD(array, 0, AADLength);
289
290
// next, generate cipher text again at the same buffer of plain text
291
int off = anotherCipher.update(array, txtOffset, length,
292
array, txtOffset);
293
anotherCipher.doFinal(array, txtOffset + off);
294
295
// check if two results are equal or not
296
if (!isEqual(array, txtOffset, outputText, 0,
297
outputText.length)) {
298
throw new RuntimeException(
299
"Two results are not equal, mode:" + mode);
300
}
301
}
302
303
/*
304
* Execute GCM encryption/decryption of textBB. AAD and text to process are
305
* placed in different byte buffers. Data are processed twice:
306
* - in a separately allocated buffer
307
* - in a buffer that shares content of the textBB
308
* Check if results are equal
309
*/
310
private void runGCMWithSeparateBuffers(int mode, ByteBuffer buffer,
311
ByteBuffer textBB, int txtOffset, int dataLength,
312
AlgorithmParameters params) throws Exception {
313
// take offset into account
314
textBB.position(txtOffset);
315
textBB.mark();
316
317
// first, generate the cipher text at an allocated buffer
318
Cipher cipher = createCipher(mode, params);
319
cipher.updateAAD(buffer);
320
buffer.flip();
321
ByteBuffer outBB = ByteBuffer.allocateDirect(
322
cipher.getOutputSize(dataLength));
323
324
cipher.doFinal(textBB, outBB);// get cipher text in outBB
325
outBB.flip();
326
327
// restore positions
328
textBB.reset();
329
330
// next, generate cipher text again in a buffer that shares content
331
Cipher anotherCipher = createCipher(mode, params);
332
anotherCipher.updateAAD(buffer);
333
buffer.flip();
334
ByteBuffer buf2 = textBB.duplicate(); // buf2 shares textBuf context
335
buf2.limit(txtOffset + anotherCipher.getOutputSize(dataLength));
336
int dataProcessed2 = anotherCipher.doFinal(textBB, buf2);
337
buf2.position(txtOffset);
338
buf2.limit(txtOffset + dataProcessed2);
339
340
if (!buf2.equals(outBB)) {
341
throw new RuntimeException(
342
"Two results are not equal, mode:" + mode);
343
}
344
}
345
346
/*
347
* Execute GCM encryption/decryption of text. AAD and a text to process are
348
* placed in the same buffer. Data is processed twice:
349
* - in a separately allocated buffer
350
* - in a buffer that shares content of the AAD_and_Text_BB
351
*/
352
private void runGCMWithSameBuffer(int mode, ByteBuffer buffer,
353
int txtOffset, int length, AlgorithmParameters params)
354
throws Exception {
355
356
// allocate a separate buffer
357
Cipher cipher = createCipher(mode, params);
358
ByteBuffer outBB = ByteBuffer.allocateDirect(
359
cipher.getOutputSize(length));
360
361
// first, generate the cipher text at an allocated buffer
362
buffer.flip();
363
buffer.limit(AADLength);
364
cipher.updateAAD(buffer);
365
buffer.limit(AADLength + txtOffset + length);
366
buffer.position(AADLength + txtOffset);
367
cipher.doFinal(buffer, outBB);
368
outBB.flip(); // cipher text in outBB
369
370
// next, generate cipherText again in the same buffer
371
Cipher anotherCipher = createCipher(mode, params);
372
buffer.flip();
373
buffer.limit(AADLength);
374
anotherCipher.updateAAD(buffer);
375
buffer.limit(AADLength + txtOffset + length);
376
buffer.position(AADLength + txtOffset);
377
378
// share textBuf context
379
ByteBuffer buf2 = buffer.duplicate();
380
buf2.limit(AADLength + txtOffset + anotherCipher.getOutputSize(length));
381
int dataProcessed2 = anotherCipher.doFinal(buffer, buf2);
382
buf2.position(AADLength + txtOffset);
383
buf2.limit(AADLength + txtOffset + dataProcessed2);
384
385
if (!buf2.equals(outBB)) {
386
throw new RuntimeException(
387
"Two results are not equal, mode:" + mode);
388
}
389
}
390
391
private boolean isEqual(byte[] A, int offsetA, byte[] B, int offsetB,
392
int bytesToCompare) {
393
System.out.println("offsetA: " + offsetA + " offsetB: " + offsetA
394
+ " bytesToCompare: " + bytesToCompare);
395
for (int i = 0; i < bytesToCompare; i++) {
396
int setA = i + offsetA;
397
int setB = i + offsetB;
398
if (setA > A.length - 1 || setB > B.length - 1
399
|| A[setA] != B[setB]) {
400
System.err.println("i = " + i + " A[setA] = " + A[setA] +
401
" B[setB] = " + B[setB]);
402
return false;
403
}
404
}
405
406
return true;
407
}
408
409
/*
410
* Creates a Cipher object for testing: for encryption it creates new Cipher
411
* based on previously saved parameters (it is prohibited to use the same
412
* Cipher twice for encription during GCM mode), or returns initiated
413
* existing Cipher.
414
*/
415
private Cipher createCipher(int mode, AlgorithmParameters params)
416
throws Exception {
417
Cipher cipher = Cipher.getInstance(transformation, provider);
418
if (Cipher.ENCRYPT_MODE == mode) {
419
// initiate it with the saved parameters
420
if (params != null) {
421
cipher.init(Cipher.ENCRYPT_MODE, key, params);
422
} else {
423
// intiate the cipher and save parameters
424
cipher.init(Cipher.ENCRYPT_MODE, key);
425
}
426
} else if (cipher != null) {
427
cipher.init(Cipher.DECRYPT_MODE, key, params);
428
} else {
429
throw new RuntimeException("Can't create cipher");
430
}
431
432
return cipher;
433
}
434
435
}
436
437