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