Skip to content

Commit cc59d57

Browse files
author
duke
committedJun 27, 2024
Automatic merge of jdk:master into master
2 parents b56ca21 + 4ab7e98 commit cc59d57

File tree

7 files changed

+597
-92
lines changed

7 files changed

+597
-92
lines changed
 

‎src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java

+22
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,11 @@ public List<String> run() {
164164
// Secmod.Module.getProvider() method.
165165
private String functionList = null;
166166

167+
// CTS mode variant used by the token, as described in Addendum to NIST
168+
// Special Publication 800-38A, "Recommendation for Block Cipher Modes
169+
// of Operation: Three Variants of Ciphertext Stealing for CBC Mode".
170+
private Token.CTSVariant ctsVariant = null;
171+
167172
// whether to use NSS secmod mode. Implicitly set if nssLibraryDirectory,
168173
// nssSecmodDirectory, or nssModule is specified.
169174
private boolean nssUseSecmod;
@@ -321,6 +326,10 @@ String getFunctionList() {
321326
return functionList;
322327
}
323328

329+
Token.CTSVariant getCTSVariant() {
330+
return ctsVariant;
331+
}
332+
324333
boolean getNssUseSecmod() {
325334
return nssUseSecmod;
326335
}
@@ -472,6 +481,8 @@ private void parse() throws IOException {
472481
allowSingleThreadedModules = parseBooleanEntry(st.sval);
473482
case "functionList"->
474483
functionList = parseStringEntry(st.sval);
484+
case "cipherTextStealingVariant"->
485+
ctsVariant = parseEnumEntry(Token.CTSVariant.class, st.sval);
475486
case "nssUseSecmod"->
476487
nssUseSecmod = parseBooleanEntry(st.sval);
477488
case "nssLibraryDirectory"-> {
@@ -627,6 +638,17 @@ private int parseIntegerEntry(String keyword) throws IOException {
627638
return value;
628639
}
629640

641+
private <E extends Enum<E>> E parseEnumEntry(Class<E> enumClass,
642+
String keyword) throws IOException {
643+
String value = parseStringEntry(keyword);
644+
try {
645+
return Enum.valueOf(enumClass, value);
646+
} catch (IllegalArgumentException ignored) {
647+
throw excToken(keyword + " must be one of " +
648+
Arrays.toString(enumClass.getEnumConstants()) + ", read:");
649+
}
650+
}
651+
630652
private boolean parseBoolean() throws IOException {
631653
String val = parseWord();
632654
return switch (val) {

‎src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java

+263-55
Large diffs are not rendered by default.

‎src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java

+16-1
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,15 @@ private static void register(Descriptor d) {
860860
dA(CIP, "AES_256/KWP/NoPadding", P11KeyWrapCipher,
861861
m(CKM_AES_KEY_WRAP_KWP));
862862

863+
d(CIP, "AES/CTS/NoPadding", P11Cipher,
864+
m(CKM_AES_CTS));
865+
d(CIP, "AES_128/CTS/NoPadding", P11Cipher,
866+
m(CKM_AES_CTS));
867+
d(CIP, "AES_192/CTS/NoPadding", P11Cipher,
868+
m(CKM_AES_CTS));
869+
d(CIP, "AES_256/CTS/NoPadding", P11Cipher,
870+
m(CKM_AES_CTS));
871+
863872
d(CIP, "AES/GCM/NoPadding", P11AEADCipher,
864873
m(CKM_AES_GCM));
865874
dA(CIP, "AES_128/GCM/NoPadding", P11AEADCipher,
@@ -1290,7 +1299,13 @@ private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {
12901299
}
12911300
continue;
12921301
}
1293-
1302+
if (longMech == CKM_AES_CTS && token.ctsVariant == null) {
1303+
if (showInfo) {
1304+
System.out.println("DISABLED due to an unspecified " +
1305+
"cipherTextStealingVariant in configuration");
1306+
}
1307+
continue;
1308+
}
12941309
if (brokenMechanisms.contains(longMech)) {
12951310
if (showInfo) {
12961311
System.out.println("DISABLED due to known issue with NSS");

‎src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Token.java

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -47,6 +47,7 @@
4747
* @since 1.5
4848
*/
4949
final class Token implements Serializable {
50+
public enum CTSVariant {CS1, CS2, CS3}
5051

5152
// need to be serializable to allow SecureRandom to be serialized
5253
@Serial
@@ -65,6 +66,8 @@ final class Token implements Serializable {
6566
@SuppressWarnings("serial") // Type of field is not Serializable
6667
final Config config;
6768

69+
final transient CTSVariant ctsVariant;
70+
6871
@SuppressWarnings("serial") // Type of field is not Serializable
6972
final CK_TOKEN_INFO tokenInfo;
7073

@@ -146,6 +149,7 @@ final class Token implements Serializable {
146149
config = provider.config;
147150
tokenInfo = p11.C_GetTokenInfo(provider.slotID);
148151
writeProtected = (tokenInfo.flags & CKF_WRITE_PROTECTED) != 0;
152+
ctsVariant = getCTSVariant();
149153
// create session manager and open a test session
150154
SessionManager sessionManager;
151155
try {
@@ -412,6 +416,19 @@ CK_MECHANISM_INFO getMechanismInfo(long mechanism) throws PKCS11Exception {
412416
return result;
413417
}
414418

419+
private CTSVariant getCTSVariant() {
420+
CTSVariant ctsVariant = config.getCTSVariant();
421+
if (ctsVariant != null) {
422+
return ctsVariant;
423+
}
424+
// 'cipherTextStealingVariant' needs an explicit value for the
425+
// CKM_AES_CTS mechanism to be enabled. In the case of NSS we know
426+
// that this value is 'CS1', so we can set it for the user. See:
427+
// https://bugzilla.mozilla.org/show_bug.cgi?id=373108#c7
428+
// https://github.com/nss-dev/nss/blob/NSS_3_99_RTM/lib/freebl/cts.c#L65
429+
return P11Util.isNSS(this) ? CTSVariant.CS1 : null;
430+
}
431+
415432
private synchronized byte[] getTokenId() {
416433
if (tokenId == null) {
417434
SecureRandom random = JCAUtil.getSecureRandom();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
/*
2+
* Copyright (c) 2024, Red Hat, Inc.
3+
*
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation.
9+
*
10+
* This code is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
* version 2 for more details (a copy is included in the LICENSE file that
14+
* accompanied this code).
15+
*
16+
* You should have received a copy of the GNU General Public License version
17+
* 2 along with this work; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19+
*
20+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21+
* or visit www.oracle.com if you need additional information or have any
22+
* questions.
23+
*/
24+
25+
import javax.crypto.Cipher;
26+
import javax.crypto.spec.IvParameterSpec;
27+
import javax.crypto.spec.SecretKeySpec;
28+
import java.nio.ByteBuffer;
29+
import java.nio.charset.StandardCharsets;
30+
import java.security.Key;
31+
import java.security.Provider;
32+
import java.util.Arrays;
33+
import java.util.HexFormat;
34+
import java.util.stream.IntStream;
35+
36+
/*
37+
* @test
38+
* @bug 8330842
39+
* @summary test AES CTS multipart operations with SunPKCS11
40+
* @library /test/lib ..
41+
* @run main/othervm/timeout=120 TestCipherTextStealingMultipart
42+
*/
43+
44+
public class TestCipherTextStealingMultipart extends PKCS11Test {
45+
private static final String LF = System.lineSeparator();
46+
private static final String ALGORITHM = "AES/CTS/NoPadding";
47+
private static final int BLOCK_SIZE = 16;
48+
private static final Key KEY =
49+
new SecretKeySpec("AbCdEfGhIjKlMnOp".getBytes(), "AES");
50+
private static final IvParameterSpec IV =
51+
new IvParameterSpec("1234567890aBcDeF".getBytes());
52+
53+
private static final StringBuilder chunksDesc = new StringBuilder();
54+
private static Provider sunPKCS11;
55+
private static Cipher sunJCECipher;
56+
57+
private static byte[][] generateChunks(int totalLength, int[] chunkSizes) {
58+
chunksDesc.setLength(0);
59+
chunksDesc.append("Testing with ").append(totalLength)
60+
.append(" bytes distributed in ").append(chunkSizes.length)
61+
.append(" multipart updates:").append(LF);
62+
int byteIdx = 0;
63+
byte[][] plaintextChunks = new byte[chunkSizes.length][];
64+
for (int chunkIdx = 0; chunkIdx < chunkSizes.length; chunkIdx++) {
65+
byte[] chunk = new byte[chunkSizes[chunkIdx]];
66+
for (int i = 0; i < chunk.length; i++) {
67+
chunk[i] = (byte) ('A' + byteIdx++ / BLOCK_SIZE);
68+
}
69+
chunksDesc.append(" ").append(repr(chunk)).append(LF);
70+
plaintextChunks[chunkIdx] = chunk;
71+
}
72+
return plaintextChunks;
73+
}
74+
75+
private static byte[] computeExpected(byte[] jointPlaintext)
76+
throws Exception {
77+
byte[] ciphertext = sunJCECipher.doFinal(jointPlaintext);
78+
if (ciphertext.length != jointPlaintext.length) {
79+
throw new Exception("In CTS mode, ciphertext and plaintext should" +
80+
" have the same length. However, SunJCE's CTS cipher " +
81+
"returned a ciphertext of " + ciphertext.length + " bytes" +
82+
" and plaintext has " + jointPlaintext.length + " bytes.");
83+
}
84+
return ciphertext;
85+
}
86+
87+
private static byte[] join(byte[][] inputChunks, int totalLength) {
88+
ByteBuffer outputBuf = ByteBuffer.allocate(totalLength);
89+
for (byte[] inputChunk : inputChunks) {
90+
outputBuf.put(inputChunk);
91+
}
92+
return outputBuf.array();
93+
}
94+
95+
private static byte[][] split(byte[] input, int[] chunkSizes) {
96+
ByteBuffer inputBuf = ByteBuffer.wrap(input);
97+
byte[][] outputChunks = new byte[chunkSizes.length][];
98+
for (int chunkIdx = 0; chunkIdx < chunkSizes.length; chunkIdx++) {
99+
byte[] chunk = new byte[chunkSizes[chunkIdx]];
100+
inputBuf.get(chunk);
101+
outputChunks[chunkIdx] = chunk;
102+
}
103+
return outputChunks;
104+
}
105+
106+
private enum CheckType {CIPHERTEXT, PLAINTEXT}
107+
108+
private enum OutputType {BYTE_ARRAY, DIRECT_BYTE_BUFFER}
109+
110+
private static void check(CheckType checkType, OutputType outputType,
111+
byte[] expected, ByteBuffer actualBuf) throws Exception {
112+
byte[] actual;
113+
if (actualBuf.hasArray()) {
114+
actual = actualBuf.array();
115+
} else {
116+
actual = new byte[actualBuf.position()];
117+
actualBuf.position(0).get(actual);
118+
}
119+
if (!Arrays.equals(actual, expected)) {
120+
throw new Exception("After " + switch (checkType) {
121+
case CIPHERTEXT -> "encrypting";
122+
case PLAINTEXT -> "decrypting";
123+
} + " into a " + switch (outputType) {
124+
case BYTE_ARRAY -> "byte[]";
125+
case DIRECT_BYTE_BUFFER -> "direct ByteBuffer";
126+
} + ", " + checkType.name().toLowerCase() + "s don't match:" + LF +
127+
" Expected: " + repr(expected) + LF +
128+
" Actual: " + repr(actual));
129+
}
130+
}
131+
132+
private static ByteBuffer encryptOrDecryptMultipart(int operation,
133+
OutputType outputType, byte[][] inputChunks, int totalLength)
134+
throws Exception {
135+
Cipher cipher = Cipher.getInstance(ALGORITHM, sunPKCS11);
136+
cipher.init(operation, KEY, IV);
137+
ByteBuffer output = null;
138+
int outOfs = 1;
139+
switch (outputType) {
140+
case BYTE_ARRAY -> {
141+
output = ByteBuffer.allocate(totalLength);
142+
for (byte[] inputChunk : inputChunks) {
143+
output.put(cipher.update(inputChunk));
144+
}
145+
// Check that the output array offset does not affect the
146+
// penultimate block length calculation.
147+
byte[] tmpOut = new byte[cipher.getOutputSize(0) + outOfs];
148+
cipher.doFinal(tmpOut, outOfs);
149+
output.put(tmpOut, outOfs, tmpOut.length - outOfs);
150+
}
151+
case DIRECT_BYTE_BUFFER -> {
152+
output = ByteBuffer.allocateDirect(totalLength);
153+
for (byte[] inputChunk : inputChunks) {
154+
cipher.update(ByteBuffer.wrap(inputChunk), output);
155+
}
156+
// Check that the output array offset does not affect the
157+
// penultimate block length calculation.
158+
ByteBuffer tmpOut = ByteBuffer.allocateDirect(
159+
cipher.getOutputSize(0) + outOfs);
160+
tmpOut.position(outOfs);
161+
cipher.doFinal(ByteBuffer.allocate(0), tmpOut);
162+
tmpOut.position(outOfs);
163+
output.put(tmpOut);
164+
}
165+
}
166+
return output;
167+
}
168+
169+
private static void doMultipart(int... chunkSizes) throws Exception {
170+
int totalLength = IntStream.of(chunkSizes).sum();
171+
byte[][] plaintextChunks = generateChunks(totalLength, chunkSizes);
172+
byte[] jointPlaintext = join(plaintextChunks, totalLength);
173+
byte[] expectedCiphertext = computeExpected(jointPlaintext);
174+
byte[][] ciphertextChunks = split(expectedCiphertext, chunkSizes);
175+
176+
for (OutputType outputType : OutputType.values()) {
177+
// Encryption test
178+
check(CheckType.CIPHERTEXT, outputType, expectedCiphertext,
179+
encryptOrDecryptMultipart(Cipher.ENCRYPT_MODE, outputType,
180+
plaintextChunks, totalLength));
181+
// Decryption test
182+
check(CheckType.PLAINTEXT, outputType, jointPlaintext,
183+
encryptOrDecryptMultipart(Cipher.DECRYPT_MODE, outputType,
184+
ciphertextChunks, totalLength));
185+
}
186+
}
187+
188+
private static String repr(byte[] data) {
189+
if (data == null) {
190+
return "<null>";
191+
}
192+
if (data.length == 0) {
193+
return "<empty []>";
194+
}
195+
String lenRepr = " (" + data.length + " bytes)";
196+
for (byte b : data) {
197+
if (b < 32 || b > 126) {
198+
return HexFormat.ofDelimiter(":").formatHex(data) + lenRepr;
199+
}
200+
}
201+
return new String(data, StandardCharsets.US_ASCII) + lenRepr;
202+
}
203+
204+
private static void initialize() throws Exception {
205+
sunJCECipher = Cipher.getInstance(ALGORITHM, "SunJCE");
206+
sunJCECipher.init(Cipher.ENCRYPT_MODE, KEY, IV);
207+
}
208+
209+
public static void main(String[] args) throws Exception {
210+
initialize();
211+
main(new TestCipherTextStealingMultipart(), args);
212+
}
213+
214+
@Override
215+
public void main(Provider p) throws Exception {
216+
sunPKCS11 = p;
217+
try {
218+
// Test relevant combinations for 2, 3, and 4 update operations
219+
int aesBSize = 16;
220+
int[] points = new int[]{1, aesBSize - 1, aesBSize, aesBSize + 1};
221+
for (int size1 : points) {
222+
for (int size2 : points) {
223+
if (size1 + size2 >= aesBSize) {
224+
doMultipart(size1, size2);
225+
}
226+
for (int size3 : points) {
227+
if (size1 + size2 + size3 >= aesBSize) {
228+
doMultipart(size1, size2, size3);
229+
}
230+
for (int size4 : points) {
231+
if (size1 + size2 + size3 + size4 >= aesBSize) {
232+
doMultipart(size1, size2, size3, size4);
233+
}
234+
}
235+
}
236+
}
237+
}
238+
doMultipart(17, 17, 17, 17, 17);
239+
doMultipart(4, 2, 7, 1, 6, 12);
240+
doMultipart(2, 15, 21, 26, 31, 26, 5, 30);
241+
doMultipart(7, 12, 26, 8, 15, 2, 17, 16, 21, 2, 32, 29);
242+
doMultipart(6, 7, 6, 1, 5, 16, 14, 1, 10, 16, 17, 8, 1, 13, 12);
243+
doMultipart(16, 125, 19, 32, 32, 16, 17,
244+
31, 19, 13, 16, 16, 32, 16, 16);
245+
doMultipart(5, 30, 11, 9, 6, 14, 20, 6,
246+
5, 18, 31, 33, 15, 29, 7, 9);
247+
doMultipart(105, 8, 21, 27, 30, 101, 15, 20,
248+
23, 33, 26, 6, 8, 2, 13, 17);
249+
} catch (Exception e) {
250+
System.out.print(chunksDesc);
251+
throw e;
252+
}
253+
System.out.println("TEST PASS - OK");
254+
}
255+
}

‎test/jdk/sun/security/pkcs11/Cipher/TestSymmCiphers.java

+15-26
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
2323

2424
/*
2525
* @test
26-
* @bug 4898461 6604496
26+
* @bug 4898461 6604496 8330842
2727
* @summary basic test for symmetric ciphers with padding
2828
* @author Valerie Peng
2929
* @library /test/lib ..
@@ -80,10 +80,11 @@ private static class CI { // class for holding Cipher Information
8080
new CI("DESede", "DESede", 408),
8181
new CI("AES", "AES", 128),
8282

83-
new CI("AES/CTR/NoPadding", "AES", 3200)
83+
new CI("AES/CTR/NoPadding", "AES", 3200),
84+
new CI("AES/CTS/NoPadding", "AES", 3200),
8485

8586
};
86-
private static StringBuffer debugBuf = new StringBuffer();
87+
private static final StringBuffer debugBuf = new StringBuffer();
8788

8889
@Override
8990
public void main(Provider p) throws Exception {
@@ -128,10 +129,7 @@ public void main(Provider p) throws Exception {
128129
}
129130
} catch (Exception ex) {
130131
// print out debug info when exception is encountered
131-
if (debugBuf != null) {
132-
System.out.println(debugBuf.toString());
133-
debugBuf = new StringBuffer();
134-
}
132+
System.out.println(debugBuf);
135133
throw ex;
136134
}
137135
}
@@ -171,8 +169,7 @@ private static void test(Cipher cipher, int mode, SecretKey key,
171169
}
172170
byte[] testOut1 = baos.toByteArray();
173171
endTime = System.nanoTime();
174-
perfOut("stream InBuf + stream OutBuf: " +
175-
(endTime - startTime));
172+
perfOut("stream InBuf + stream OutBuf", endTime - startTime);
176173
match(testOut1, answer);
177174

178175
// test#2: Non-direct Buffer in + non-direct Buffer out
@@ -184,8 +181,7 @@ private static void test(Cipher cipher, int mode, SecretKey key,
184181
cipher.update(inBuf, outBuf);
185182
cipher.doFinal(inBuf, outBuf);
186183
endTime = System.nanoTime();
187-
perfOut("non-direct InBuf + non-direct OutBuf: " +
188-
(endTime - startTime));
184+
perfOut("non-direct InBuf + non-direct OutBuf", endTime - startTime);
189185
match(outBuf, answer);
190186

191187
// test#3: Direct Buffer in + direc Buffer out
@@ -197,8 +193,7 @@ private static void test(Cipher cipher, int mode, SecretKey key,
197193
cipher.update(inDirectBuf, outDirectBuf);
198194
cipher.doFinal(inDirectBuf, outDirectBuf);
199195
endTime = System.nanoTime();
200-
perfOut("direct InBuf + direct OutBuf: " +
201-
(endTime - startTime));
196+
perfOut("direct InBuf + direct OutBuf", endTime - startTime);
202197

203198
//debugOut("(post) inputBuf: " + inDirectBuf + "\n");
204199
//debugOut("(post) outputBuf: " + outDirectBuf + "\n");
@@ -215,8 +210,7 @@ private static void test(Cipher cipher, int mode, SecretKey key,
215210
cipher.update(inDirectBuf, outBuf);
216211
cipher.doFinal(inDirectBuf, outBuf);
217212
endTime = System.nanoTime();
218-
perfOut("direct InBuf + non-direct OutBuf: " +
219-
(endTime - startTime));
213+
perfOut("direct InBuf + non-direct OutBuf", endTime - startTime);
220214
match(outBuf, answer);
221215

222216
// test#5: Non-direct Buffer in + direct Buffer out
@@ -231,26 +225,21 @@ private static void test(Cipher cipher, int mode, SecretKey key,
231225
cipher.update(inBuf, outDirectBuf);
232226
cipher.doFinal(inBuf, outDirectBuf);
233227
endTime = System.nanoTime();
234-
perfOut("non-direct InBuf + direct OutBuf: " +
235-
(endTime - startTime));
228+
perfOut("non-direct InBuf + direct OutBuf", endTime - startTime);
236229

237230
//debugOut("(post) inputBuf: " + inBuf + "\n");
238231
//debugOut("(post) outputBuf: " + outDirectBuf + "\n");
239232
match(outDirectBuf, answer);
240233

241-
debugBuf = null;
234+
debugBuf.setLength(0);
242235
}
243236

244-
private static void perfOut(String msg) {
245-
if (debugBuf != null) {
246-
debugBuf.append("PERF>" + msg);
247-
}
237+
private static void perfOut(String msg, long elapsed) {
238+
debugOut("PERF> " + msg + ", elapsed: " + elapsed + " ns\n");
248239
}
249240

250241
private static void debugOut(String msg) {
251-
if (debugBuf != null) {
252-
debugBuf.append(msg);
253-
}
242+
debugBuf.append(msg);
254243
}
255244

256245
private static void match(byte[] b1, byte[] b2) throws Exception {

‎test/jdk/sun/security/pkcs11/Cipher/TestSymmCiphersNoPad.java

+8-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
2323

2424
/*
2525
* @test
26-
* @bug 4898484 6604496 8001284
26+
* @bug 4898484 6604496 8001284 8330842
2727
* @summary basic test for symmetric ciphers with no padding
2828
* @author Valerie Peng
2929
* @library /test/lib ..
@@ -68,10 +68,12 @@ private static class CI { // class for holding Cipher Information
6868
new CI("AES/CBC/NoPadding", "AES", 4800),
6969
new CI("Blowfish/CBC/NoPadding", "Blowfish", 24),
7070
new CI("AES/CTR/NoPadding", "AES", 1600),
71-
new CI("AES/CTR/NoPadding", "AES", 65)
71+
new CI("AES/CTR/NoPadding", "AES", 65),
72+
new CI("AES/CTS/NoPadding", "AES", 1600),
73+
new CI("AES/CTS/NoPadding", "AES", 65),
7274
};
7375

74-
private static StringBuffer debugBuf;
76+
private static final StringBuffer debugBuf = new StringBuffer();
7577

7678
@Override
7779
public void main(Provider p) throws Exception {
@@ -111,9 +113,7 @@ public void main(Provider p) throws Exception {
111113
}
112114
} catch (Exception ex) {
113115
// print out debug info when exception is encountered
114-
if (debugBuf != null) {
115-
System.out.println(debugBuf.toString());
116-
}
116+
System.out.println(debugBuf);
117117
throw ex;
118118
}
119119
}
@@ -122,7 +122,6 @@ private static void test(Cipher cipher, int mode, SecretKey key,
122122
AlgorithmParameters params,
123123
byte[] in, byte[] answer) throws Exception {
124124
// test setup
125-
debugBuf = new StringBuffer();
126125
cipher.init(mode, key, params);
127126
int outLen = cipher.getOutputSize(in.length);
128127
debugBuf.append("Estimated output size = " + outLen + "\n");
@@ -214,7 +213,7 @@ private static void test(Cipher cipher, int mode, SecretKey key,
214213
}
215214
match(outBuf, answer);
216215

217-
debugBuf = null;
216+
debugBuf.setLength(0);
218217
}
219218

220219
private static void match(byte[] b1, byte[] b2) throws Exception {

0 commit comments

Comments
 (0)
Please sign in to comment.