manRef;
private JarEntry manEntry;
@@ -800,8 +799,11 @@ private void initializeVerifier() {
private byte[] getBytes(ZipEntry ze) throws IOException {
try (InputStream is = super.getInputStream(ze)) {
long uncompressedSize = ze.getSize();
- if (uncompressedSize > MAX_ARRAY_SIZE) {
- throw new IOException("Unsupported size: " + uncompressedSize);
+ if (uncompressedSize > SignatureFileVerifier.MAX_SIG_FILE_SIZE) {
+ throw new IOException("Unsupported size: " + uncompressedSize +
+ " for JarEntry " + ze.getName() +
+ ". Allowed max size: " +
+ SignatureFileVerifier.MAX_SIG_FILE_SIZE + " bytes");
}
int len = (int)uncompressedSize;
int bytesRead;
diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java
index f073fe8fb1b..a2573f83f66 100644
--- a/src/java.base/share/classes/java/util/zip/ZipFile.java
+++ b/src/java.base/share/classes/java/util/zip/ZipFile.java
@@ -69,6 +69,7 @@
import jdk.internal.ref.CleanerFactory;
import jdk.internal.vm.annotation.Stable;
import sun.nio.cs.UTF_8;
+import sun.security.action.GetBooleanAction;
import sun.security.util.SignatureFileVerifier;
import static java.util.zip.ZipConstants64.*;
@@ -121,6 +122,12 @@ public class ZipFile implements ZipConstants, Closeable {
*/
public static final int OPEN_DELETE = 0x4;
+ /**
+ * Flag which specifies whether the validation of the Zip64 extra
+ * fields should be disabled
+ */
+ private static final boolean disableZip64ExtraFieldValidation =
+ GetBooleanAction.privilegedGetProperty("jdk.util.zip.disableZip64ExtraFieldValidation");
/**
* Opens a zip file for reading.
*
@@ -1195,6 +1202,16 @@ private int checkAndAddEntry(int pos, int index)
if (entryPos + nlen > cen.length - ENDHDR) {
zerror("invalid CEN header (bad header size)");
}
+
+ int elen = CENEXT(cen, pos);
+ if (elen > 0 && !disableZip64ExtraFieldValidation) {
+ long extraStartingOffset = pos + CENHDR + nlen;
+ if ((int)extraStartingOffset != extraStartingOffset) {
+ zerror("invalid CEN header (bad extra offset)");
+ }
+ checkExtraFields(pos, (int)extraStartingOffset, elen);
+ }
+
try {
ZipCoder zcp = zipCoderForPos(pos);
int hash = zcp.checkedHash(cen, entryPos, nlen);
@@ -1211,6 +1228,119 @@ private int checkAndAddEntry(int pos, int index)
return nlen;
}
+ /**
+ * Validate the Zip64 Extra block fields
+ * @param startingOffset Extra Field starting offset within the CEN
+ * @param extraFieldLen Length of this Extra field
+ * @throws ZipException If an error occurs validating the Zip64 Extra
+ * block
+ */
+ private void checkExtraFields(int cenPos, int startingOffset,
+ int extraFieldLen) throws ZipException {
+ // Extra field Length cannot exceed 65,535 bytes per the PKWare
+ // APP.note 4.4.11
+ if (extraFieldLen > 0xFFFF) {
+ zerror("invalid extra field length");
+ }
+ // CEN Offset where this Extra field ends
+ int extraEndOffset = startingOffset + extraFieldLen;
+ if (extraEndOffset > cen.length) {
+ zerror("Invalid CEN header (extra data field size too long)");
+ }
+ int currentOffset = startingOffset;
+ while (currentOffset < extraEndOffset) {
+ int tag = get16(cen, currentOffset);
+ currentOffset += Short.BYTES;
+
+ int tagBlockSize = get16(cen, currentOffset);
+ int tagBlockEndingOffset = currentOffset + tagBlockSize;
+
+ // The ending offset for this tag block should not go past the
+ // offset for the end of the extra field
+ if (tagBlockEndingOffset > extraEndOffset) {
+ zerror("Invalid CEN header (invalid zip64 extra data field size)");
+ }
+ currentOffset += Short.BYTES;
+
+ if (tag == ZIP64_EXTID) {
+ // Get the compressed size;
+ long csize = CENSIZ(cen, cenPos);
+ // Get the uncompressed size;
+ long size = CENLEN(cen, cenPos);
+ checkZip64ExtraFieldValues(currentOffset, tagBlockSize,
+ csize, size);
+ }
+ currentOffset += tagBlockSize;
+ }
+ }
+
+ /**
+ * Validate the Zip64 Extended Information Extra Field (0x0001) block
+ * size and that the uncompressed size and compressed size field
+ * values are not negative.
+ * Note: As we do not use the LOC offset or Starting disk number
+ * field value we will not validate them
+ * @param off the starting offset for the Zip64 field value
+ * @param blockSize the size of the Zip64 Extended Extra Field
+ * @param csize CEN header compressed size value
+ * @param size CEN header uncompressed size value
+ * @throws ZipException if an error occurs
+ */
+ private void checkZip64ExtraFieldValues(int off, int blockSize, long csize,
+ long size)
+ throws ZipException {
+ byte[] cen = this.cen;
+ // Validate the Zip64 Extended Information Extra Field (0x0001)
+ // length.
+ if (!isZip64ExtBlockSizeValid(blockSize)) {
+ zerror("Invalid CEN header (invalid zip64 extra data field size)");
+ }
+ // Check the uncompressed size is not negative
+ // Note we do not need to check blockSize is >= 8 as
+ // we know its length is at least 8 from the call to
+ // isZip64ExtBlockSizeValid()
+ if ((size == ZIP64_MAGICVAL)) {
+ if(get64(cen, off) < 0) {
+ zerror("Invalid zip64 extra block size value");
+ }
+ }
+ // Check the compressed size is not negative
+ if ((csize == ZIP64_MAGICVAL) && (blockSize >= 16)) {
+ if (get64(cen, off + 8) < 0) {
+ zerror("Invalid zip64 extra block compressed size value");
+ }
+ }
+ }
+
+ /**
+ * Validate the size and contents of a Zip64 extended information field
+ * The order of the Zip64 fields is fixed, but the fields MUST
+ * only appear if the corresponding LOC or CEN field is set to 0xFFFF:
+ * or 0xFFFFFFFF:
+ * Uncompressed Size - 8 bytes
+ * Compressed Size - 8 bytes
+ * LOC Header offset - 8 bytes
+ * Disk Start Number - 4 bytes
+ * See PKWare APP.Note Section 4.5.3 for more details
+ *
+ * @param blockSize the Zip64 Extended Information Extra Field size
+ * @return true if the extra block size is valid; false otherwise
+ */
+ private static boolean isZip64ExtBlockSizeValid(int blockSize) {
+ /*
+ * As the fields must appear in order, the block size indicates which
+ * fields to expect:
+ * 8 - uncompressed size
+ * 16 - uncompressed size, compressed size
+ * 24 - uncompressed size, compressed sise, LOC Header offset
+ * 28 - uncompressed size, compressed sise, LOC Header offset,
+ * and Disk start number
+ */
+ return switch(blockSize) {
+ case 8, 16, 24, 28 -> true;
+ default -> false;
+ };
+ }
private int getEntryHash(int index) { return entries[index]; }
private int getEntryNext(int index) { return entries[index + 1]; }
private int getEntryPos(int index) { return entries[index + 2]; }
diff --git a/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java b/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java
index d07152eeb18..4ea9255ba0a 100644
--- a/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java
+++ b/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -52,6 +52,7 @@
import java.util.jar.JarFile;
import java.util.jar.Manifest;
+import sun.security.action.GetIntegerAction;
import sun.security.jca.Providers;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
@@ -97,6 +98,12 @@ public class SignatureFileVerifier {
/** ConstraintsParameters for checking disabled algorithms */
private JarConstraintsParameters params;
+ // the maximum allowed size in bytes for the signature-related files
+ public static final int MAX_SIG_FILE_SIZE = initializeMaxSigFileSize();
+
+ // The maximum size of array to allocate. Some VMs reserve some header words in an array.
+ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
+
/**
* Create the named SignatureFileVerifier.
*
@@ -842,4 +849,24 @@ void updateSigners(CodeSigner[] newSigners,
signerCache.add(cachedSigners);
signers.put(name, cachedSigners);
}
+
+ private static int initializeMaxSigFileSize() {
+ /*
+ * System property "jdk.jar.maxSignatureFileSize" used to configure
+ * the maximum allowed number of bytes for the signature-related files
+ * in a JAR file.
+ */
+ Integer tmp = GetIntegerAction.privilegedGetProperty(
+ "jdk.jar.maxSignatureFileSize", 8000000);
+ if (tmp < 0 || tmp > MAX_ARRAY_SIZE) {
+ if (debug != null) {
+ debug.println("Default signature file size 8000000 bytes " +
+ "is used as the specified size for the " +
+ "jdk.jar.maxSignatureFileSize system property " +
+ "is out of range: " + tmp);
+ }
+ tmp = 8000000;
+ }
+ return tmp;
+ }
}
diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security
index d7520cc9ffd..7fe0e69659b 100644
--- a/src/java.base/share/conf/security/java.security
+++ b/src/java.base/share/conf/security/java.security
@@ -954,7 +954,8 @@ jdk.tls.legacyAlgorithms=NULL, anon, RC4, DES, 3DES_EDE_CBC
# Note: This property is currently used by OpenJDK's JSSE implementation. It
# is not guaranteed to be examined and used by other implementations.
#
-jdk.tls.keyLimits=AES/GCM/NoPadding KeyUpdate 2^37
+jdk.tls.keyLimits=AES/GCM/NoPadding KeyUpdate 2^37, \
+ ChaCha20-Poly1305 KeyUpdate 2^37
#
# Cryptographic Jurisdiction Policy defaults
diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java b/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java
index a315f863021..08efc2b35a4 100644
--- a/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java
@@ -75,10 +75,6 @@ static Path fromUri(UnixFileSystem fs, URI uri) {
int pos = 0;
while (pos < len) {
char c = p.charAt(pos++);
- if ((c == '/') && (pos < len) && (p.charAt(pos) == '/')) {
- // skip redundant slashes
- continue;
- }
byte b;
if (c == '%') {
assert (pos+2) <= len;
@@ -92,6 +88,10 @@ static Path fromUri(UnixFileSystem fs, URI uri) {
throw new IllegalArgumentException("Bad escape");
b = (byte)c;
}
+ if (b == '/' && rlen > 0 && result[rlen-1] == '/') {
+ // skip redundant slashes
+ continue;
+ }
result[rlen++] = b;
}
if (rlen != result.length)
diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m
index a35d5401474..1e2ba23d9aa 100644
--- a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m
+++ b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m
@@ -102,7 +102,7 @@ + (AWTStrike *) awtStrikeForFont:(AWTFont *)awtFont
#define AWT_FONT_CLEANUP_FINISH \
if (_fontThrowJavaException == YES) { \
char s[512]; \
- sprintf(s, "%s-%s:%d", __FILE__, __FUNCTION__, __LINE__); \
+ snprintf(s, sizeof(s), "%s-%s:%d", __FILE__, __FUNCTION__, __LINE__); \
JNU_ThrowByName(env, "java/lang/RuntimeException", s); \
}
diff --git a/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp b/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp
index ed2de311c22..5f868f6e408 100644
--- a/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp
+++ b/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp
@@ -635,7 +635,7 @@ void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
if (channelName == NULL) {
return;
}
- sprintf(channelName, "Ch %d", ch);
+ snprintf(channelName, 16, "Ch %d", ch);
}
void* jControls[2];
diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java
index 52c7ab078c3..910d13668d2 100644
--- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java
+++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java
@@ -615,6 +615,18 @@ public void load(InputStream input, Class> resourceBase) throws
* new URL(synthFile, path)
. Refer to
* Synth File Format for more
* information.
+ *
+ * Whilst this API may be safe for loading local resources that are
+ * delivered with a {@code LookAndFeel} or application, and so have an
+ * equal level of trust with application code, using it to load from
+ * remote resources, particularly any which may have a lower level of
+ * trust, is strongly discouraged.
+ * The alternative mechanisms to load styles from an {@code InputStream}
+ * {@linkplain #load(InputStream, Class)}
+ * using resources co-located with the application or by providing a
+ * {@code SynthStyleFactory} to
+ * {@linkplain #setStyleFactory setStyleFactory(SynthStyleFactory)}
+ * are preferred.
*
* @param url the URL
to load the set of
* SynthStyle
from
diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html b/src/java.desktop/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html
index 8eb1bbda9c1..7d63fa16dca 100644
--- a/src/java.desktop/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html
+++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html
@@ -70,6 +70,8 @@
This example loads the look and feel from an input stream, using
the specified class as the resource base to resolve paths.
+
+
It is also possible to load a look and feel from an arbitrary URL
as in the following example.
@@ -94,6 +96,11 @@
Remote JAR file, e.g.
jar:http://host/synth-laf.jar!/laf.xml
+ Note: Synth's file format allows for the definition of code to be executed.
+ Loading any code from a remote location should be used only
+ with extreme caution from a trusted source over a secure connection.
+ It is strongly discouraged for an application or a LookAndFeel to do so.
+
While the DTD for synth is specified, the parser is not validating.
Parsing will fail only if a necessary attribute is not
diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java
index 329f183ce7a..66d89ae1fc5 100644
--- a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java
@@ -45,6 +45,7 @@
import java.net.http.HttpResponse.BodyHandler;
import java.net.http.HttpResponse.ResponseInfo;
import java.net.http.HttpResponse.BodySubscriber;
+import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jdk.internal.net.http.ResponseSubscribers.PathSubscriber;
@@ -229,16 +230,120 @@ private FileDownloadBodyHandler(Path directory,
static final String DISPOSITION_TYPE = "attachment;";
/** The "filename" parameter. */
- static final Pattern FILENAME = Pattern.compile("filename\\s*=", CASE_INSENSITIVE);
+ static final Pattern FILENAME = Pattern.compile("filename\\s*=\\s*", CASE_INSENSITIVE);
static final List PROHIBITED = List.of(".", "..", "", "~" , "|");
+ // Characters disallowed in token values
+
+ static final Set NOT_ALLOWED_IN_TOKEN = Set.of(
+ '(', ')', '<', '>', '@',
+ ',', ';', ':', '\\', '"',
+ '/', '[', ']', '?', '=',
+ '{', '}', ' ', '\t');
+
+ static boolean allowedInToken(char c) {
+ if (NOT_ALLOWED_IN_TOKEN.contains(c))
+ return false;
+ // exclude CTL chars <= 31, == 127, or anything >= 128
+ return isTokenText(c);
+ }
+
static final UncheckedIOException unchecked(ResponseInfo rinfo,
String msg) {
String s = String.format("%s in response [%d, %s]", msg, rinfo.statusCode(), rinfo.headers());
return new UncheckedIOException(new IOException(s));
}
+ static final UncheckedIOException unchecked(String msg) {
+ return new UncheckedIOException(new IOException(msg));
+ }
+
+ // Process a "filename=" parameter, which is either a "token"
+ // or a "quoted string". If a token, it is terminated by a
+ // semicolon or the end of the string.
+ // If a quoted string (surrounded by "" chars then the closing "
+ // terminates the name.
+ // quoted strings may contain quoted-pairs (eg embedded " chars)
+
+ static String processFilename(String src) throws UncheckedIOException {
+ if ("".equals(src))
+ return src;
+ if (src.charAt(0) == '\"') {
+ return processQuotedString(src.substring(1));
+ } else {
+ return processToken(src);
+ }
+ }
+
+ static boolean isTokenText(char c) throws UncheckedIOException {
+ return c > 31 && c < 127;
+ }
+
+ static boolean isQuotedStringText(char c) throws UncheckedIOException {
+ return c > 31;
+ }
+
+ static String processQuotedString(String src) throws UncheckedIOException {
+ boolean inqpair = false;
+ int len = src.length();
+ StringBuilder sb = new StringBuilder();
+
+ for (int i=0; i apply(ResponseInfo responseInfo) {
String dispoHeader = responseInfo.headers().firstValue("Content-Disposition")
@@ -256,13 +361,7 @@ public BodySubscriber apply(ResponseInfo responseInfo) {
}
int n = matcher.end();
- int semi = dispoHeader.substring(n).indexOf(";");
- String filenameParam;
- if (semi < 0) {
- filenameParam = dispoHeader.substring(n);
- } else {
- filenameParam = dispoHeader.substring(n, n + semi);
- }
+ String filenameParam = processFilename(dispoHeader.substring(n));
// strip all but the last path segment
int x = filenameParam.lastIndexOf("/");
@@ -276,19 +375,6 @@ public BodySubscriber apply(ResponseInfo responseInfo) {
filenameParam = filenameParam.trim();
- if (filenameParam.startsWith("\"")) { // quoted-string
- if (!filenameParam.endsWith("\"") || filenameParam.length() == 1) {
- throw unchecked(responseInfo,
- "Badly quoted Content-Disposition filename parameter");
- }
- filenameParam = filenameParam.substring(1, filenameParam.length() -1 );
- } else { // token,
- if (filenameParam.contains(" ")) { // space disallowed
- throw unchecked(responseInfo,
- "unquoted space in Content-Disposition filename parameter");
- }
- }
-
if (PROHIBITED.contains(filenameParam)) {
throw unchecked(responseInfo,
"Prohibited Content-Disposition filename parameter:"
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java
index 48722d9ee7d..af0ec301f01 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java
@@ -343,6 +343,24 @@ static SecretKey secretKey(Session session, long keyID, String algorithm,
new CK_ATTRIBUTE(CKA_SENSITIVE),
new CK_ATTRIBUTE(CKA_EXTRACTABLE),
});
+
+ if ((SunPKCS11.mysunpkcs11 != null) && !SunPKCS11.isExportWrapKey.get()
+ && ("AES".equals(algorithm) || "TripleDES".equals(algorithm))
+ ) {
+ if (attributes[0].getBoolean() || attributes[1].getBoolean() || (attributes[2].getBoolean() == false)) {
+ try {
+ byte[] key = SunPKCS11.mysunpkcs11.exportKey(session.id(), attributes, keyID);
+ SecretKey secretKey = new SecretKeySpec(key, algorithm);
+ return new P11SecretKeyFIPS(session, keyID, algorithm, keyLength, attributes, secretKey);
+ } catch (PKCS11Exception e) {
+ // Attempt failed, create a P11SecretKey object.
+ if (debug != null) {
+ debug.println("Attempt failed, creating a SecretKey object for " + algorithm);
+ }
+ }
+ }
+ }
+
return new P11SecretKey(session, keyID, algorithm, keyLength,
attributes);
}
@@ -495,6 +513,29 @@ byte[] getEncodedInternal() {
}
}
+ private static final class P11SecretKeyFIPS extends P11Key implements SecretKey {
+ @Serial
+ private static final long serialVersionUID = -9186806495402041696L;
+ private final SecretKey key;
+
+ P11SecretKeyFIPS(Session session, long keyID, String algorithm,
+ int keyLength, CK_ATTRIBUTE[] attributes, SecretKey key) {
+ super(SECRET, session, keyID, algorithm, keyLength, attributes);
+ this.key = key;
+ }
+
+ @Override
+ public String getFormat() {
+ return "RAW";
+ }
+
+ @Override
+ byte[] getEncodedInternal() {
+ return key.getEncoded();
+ }
+
+ }
+
private static class P11SecretKey extends P11Key implements SecretKey {
private static final long serialVersionUID = -7828241727014329084L;
private volatile byte[] encoded;
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
index 00718ced660..f052e980cde 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
@@ -120,6 +120,8 @@ public final class SunPKCS11 extends AuthProvider {
// FIPS mode.
static SunPKCS11 mysunpkcs11;
+ static final ThreadLocal isExportWrapKey = ThreadLocal.withInitial(() -> Boolean.FALSE);
+
Token getToken() {
return token;
}
@@ -502,10 +504,12 @@ byte[] exportKey(long hSession, CK_ATTRIBUTE[] attributes, long keyId) throws PK
try {
long genKeyId = token.p11.C_GenerateKey(wrapKeyGenSession.id(), new CK_MECHANISM(CKM_AES_KEY_GEN), wrapKeyAttributes);
+ isExportWrapKey.set(Boolean.TRUE);
wrapKey = (P11Key)P11Key.secretKey(wrapKeyGenSession, genKeyId, "AES", 256 >> 3, null);
} catch (PKCS11Exception e) {
throw e;
} finally {
+ isExportWrapKey.set(Boolean.FALSE);
token.releaseSession(wrapKeyGenSession);
}
diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java
index cff2dc4d6bb..df75739188f 100644
--- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java
+++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -728,6 +728,13 @@ void verifyJar(String jarName)
&& SignatureFileVerifier.isBlockOrSF(name)) {
String alias = name.substring(name.lastIndexOf('/') + 1,
name.lastIndexOf('.'));
+ long uncompressedSize = je.getSize();
+ if (uncompressedSize > SignatureFileVerifier.MAX_SIG_FILE_SIZE) {
+ unparsableSignatures.putIfAbsent(alias, String.format(
+ rb.getString("history.unparsable"), name));
+ continue;
+ }
+
try {
if (name.endsWith(".SF")) {
Manifest sf = new Manifest(is);
diff --git a/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiInitiator.java b/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiInitiator.java
index d06d587f277..61ddf1759ef 100644
--- a/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiInitiator.java
+++ b/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiInitiator.java
@@ -79,7 +79,8 @@ public class JdiInitiator {
* @param timeout the start-up time-out in milliseconds. If zero or negative,
* will not wait thus will timeout immediately if not already started.
* @param customConnectorArgs custom arguments passed to the connector.
- * These are JDI com.sun.jdi.connect.Connector arguments.
+ * These are JDI com.sun.jdi.connect.Connector arguments. The {@code vmexec}
+ * argument is not supported.
*/
public JdiInitiator(int port, List remoteVMOptions, String remoteAgent,
boolean isLaunch, String host, int timeout,
@@ -104,7 +105,10 @@ public JdiInitiator(int port, List remoteVMOptions, String remoteAgent,
argumentName2Value.put("localAddress", host);
}
}
- argumentName2Value.putAll(customConnectorArgs);
+ customConnectorArgs.entrySet()
+ .stream()
+ .filter(e -> !"vmexec".equals(e.getKey()))
+ .forEach(e -> argumentName2Value.put(e.getKey(), e.getValue()));
this.connectorArgs = mergeConnectorArgs(connector, argumentName2Value);
this.vm = isLaunch
? launchTarget()
diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java
index 1ce7c2d8783..886be5794ba 100644
--- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java
+++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -3063,6 +3063,11 @@ private void readExtra(ZipFileSystem zipfs) throws IOException {
if (extra == null)
return;
int elen = extra.length;
+ // Extra field Length cannot exceed 65,535 bytes per the PKWare
+ // APP.note 4.4.11
+ if (elen > 0xFFFF) {
+ throw new ZipException("invalid extra field length");
+ }
int off = 0;
int newOff = 0;
boolean hasZip64LocOffset = false;
@@ -3072,26 +3077,40 @@ private void readExtra(ZipFileSystem zipfs) throws IOException {
int tag = SH(extra, pos);
int sz = SH(extra, pos + 2);
pos += 4;
- if (pos + sz > elen) // invalid data
- break;
+ if (pos + sz > elen) { // invalid data
+ throw new ZipException("Invalid CEN header (invalid zip64 extra data field size)");
+ }
switch (tag) {
case EXTID_ZIP64 :
+ // Check to see if we have a valid block size
+ if (!isZip64ExtBlockSizeValid(sz)) {
+ throw new ZipException("Invalid CEN header (invalid zip64 extra data field size)");
+ }
if (size == ZIP64_MINVAL) {
if (pos + 8 > elen) // invalid zip64 extra
break; // fields, just skip
size = LL(extra, pos);
+ if (size < 0) {
+ throw new ZipException("Invalid zip64 extra block size value");
+ }
pos += 8;
}
if (csize == ZIP64_MINVAL) {
if (pos + 8 > elen)
break;
csize = LL(extra, pos);
+ if (csize < 0) {
+ throw new ZipException("Invalid zip64 extra block compressed size value");
+ }
pos += 8;
}
if (locoff == ZIP64_MINVAL) {
if (pos + 8 > elen)
break;
locoff = LL(extra, pos);
+ if (locoff < 0) {
+ throw new ZipException("Invalid zip64 extra block LOC offset value");
+ }
}
break;
case EXTID_NTFS:
@@ -3149,6 +3168,36 @@ private void readExtra(ZipFileSystem zipfs) throws IOException {
extra = null;
}
+ /**
+ * Validate the size and contents of a Zip64 extended information field
+ * The order of the Zip64 fields is fixed, but the fields MUST
+ * only appear if the corresponding LOC or CEN field is set to 0xFFFF:
+ * or 0xFFFFFFFF:
+ * Uncompressed Size - 8 bytes
+ * Compressed Size - 8 bytes
+ * LOC Header offset - 8 bytes
+ * Disk Start Number - 4 bytes
+ * See PKWare APP.Note Section 4.5.3 for more details
+ *
+ * @param blockSize the Zip64 Extended Information Extra Field size
+ * @return true if the extra block size is valid; false otherwise
+ */
+ private static boolean isZip64ExtBlockSizeValid(int blockSize) {
+ /*
+ * As the fields must appear in order, the block size indicates which
+ * fields to expect:
+ * 8 - uncompressed size
+ * 16 - uncompressed size, compressed size
+ * 24 - uncompressed size, compressed sise, LOC Header offset
+ * 28 - uncompressed size, compressed sise, LOC Header offset,
+ * and Disk start number
+ */
+ return switch(blockSize) {
+ case 8, 16, 24, 28 -> true;
+ default -> false;
+ };
+ }
+
/**
* Read the LOC extra field to obtain the Info-ZIP Extended Timestamp fields
* @param zipfs The Zip FS to use
diff --git a/test/hotspot/jtreg/compiler/codegen/aes/CTR_Wraparound.java b/test/hotspot/jtreg/compiler/codegen/aes/CTR_Wraparound.java
new file mode 100644
index 00000000000..0bf6d3a5b8c
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/codegen/aes/CTR_Wraparound.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Check for 128-bit AES/CTR wraparound
+ * @library /test/lib /
+ * @build jdk.test.whitebox.WhiteBox
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
+ *
+ * @run main/othervm -Xbatch
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * compiler.codegen.aes.CTR_Wraparound 32
+ * @run main/othervm -Xbatch
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * compiler.codegen.aes.CTR_Wraparound 1009
+ * @run main/othervm -Xbatch
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * compiler.codegen.aes.CTR_Wraparound 2048
+ */
+
+package compiler.codegen.aes;
+
+import java.util.Arrays;
+import java.util.Random;
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import compiler.whitebox.CompilerWhiteBoxTest;
+import jdk.test.whitebox.code.Compiler;
+import jdk.test.lib.Utils;
+import jtreg.SkippedException;
+
+public class CTR_Wraparound {
+ private static final String ALGO = "AES/CTR/NoPadding";
+ private static final int LOOPS = 100000;
+
+ public static void main(String[] args) throws Exception {
+ int length = Integer.parseInt(args[0]);
+ int maxOffset = 60;
+ if (args.length > 1) {
+ maxOffset = Integer.parseInt(args[1]);
+ System.out.println("InitialOffset = " + maxOffset);
+ }
+
+ if (!Compiler.isIntrinsicAvailable(CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION, "com.sun.crypto.provider.CounterMode", "implCrypt", byte[].class, int.class, int.class, byte[].class, int.class)) {
+ throw new SkippedException("AES-CTR intrinsic is not available");
+ }
+
+ Random random = Utils.getRandomInstance();
+
+ byte[] keyBytes = new byte[32];
+ Arrays.fill(keyBytes, (byte)0xff);
+ SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
+
+ byte[] ivBytes = new byte[16];
+
+ Arrays.fill(ivBytes, (byte)0xff);
+
+ byte[][] plaintext = new byte[maxOffset][];
+ byte[][] ciphertext = new byte[maxOffset][];
+
+ for (int offset = 0; offset < maxOffset; offset++) {
+ ivBytes[ivBytes.length - 1] = (byte)-offset;
+ IvParameterSpec iv = new IvParameterSpec(ivBytes);
+
+ Cipher encryptCipher = Cipher.getInstance(ALGO);
+ Cipher decryptCipher = Cipher.getInstance(ALGO);
+
+ encryptCipher.init(Cipher.ENCRYPT_MODE, key, iv);
+ decryptCipher.init(Cipher.DECRYPT_MODE, key, iv);
+
+ plaintext[offset] = new byte[length];
+ ciphertext[offset] = new byte[length];
+ random.nextBytes(plaintext[offset]);
+
+ byte[] decrypted = new byte[length];
+
+ encryptCipher.doFinal(plaintext[offset], 0, length, ciphertext[offset]);
+ decryptCipher.doFinal(ciphertext[offset], 0, length, decrypted);
+
+ if (!Arrays.equals(plaintext[offset], decrypted)) {
+ throw new Exception("mismatch in setup at offset " + offset);
+ }
+ }
+
+ for (int offset = 0; offset < maxOffset; offset++) {
+ ivBytes[ivBytes.length - 1] = (byte)-offset;
+ IvParameterSpec iv = new IvParameterSpec(ivBytes);
+
+ Cipher encryptCipher = Cipher.getInstance(ALGO);
+
+ encryptCipher.init(Cipher.ENCRYPT_MODE, key, iv);
+
+ byte[] encrypted = new byte[length];
+
+ for (int i = 0; i < LOOPS; i++) {
+ encryptCipher.doFinal(plaintext[offset], 0, length, encrypted);
+ if (!Arrays.equals(ciphertext[offset], encrypted)) {
+ throw new Exception("array mismatch at offset " + offset
+ + " with length " + length);
+ }
+ }
+ }
+ }
+}
diff --git a/test/jdk/java/net/httpclient/AsFileDownloadTest.java b/test/jdk/java/net/httpclient/AsFileDownloadTest.java
index 2d22a1a841f..890f0701b94 100644
--- a/test/jdk/java/net/httpclient/AsFileDownloadTest.java
+++ b/test/jdk/java/net/httpclient/AsFileDownloadTest.java
@@ -24,7 +24,7 @@
/*
* @test
* @summary Basic test for ofFileDownload
- * @bug 8196965
+ * @bug 8196965 8302475
* @modules java.base/sun.net.www.http
* java.net.http/jdk.internal.net.http.common
* java.net.http/jdk.internal.net.http.frame
@@ -127,18 +127,18 @@ public class AsFileDownloadTest {
{ "024", "attachment; filename=me.txt; filename*=utf-8''you.txt", "me.txt" },
{ "025", "attachment; filename=\"m y.txt\"; filename*=utf-8''you.txt", "m y.txt" },
- { "030", "attachment; filename=foo/file1.txt", "file1.txt" },
- { "031", "attachment; filename=foo/bar/file2.txt", "file2.txt" },
- { "032", "attachment; filename=baz\\file3.txt", "file3.txt" },
- { "033", "attachment; filename=baz\\bar\\file4.txt", "file4.txt" },
- { "034", "attachment; filename=x/y\\file5.txt", "file5.txt" },
- { "035", "attachment; filename=x/y\\file6.txt", "file6.txt" },
- { "036", "attachment; filename=x/y\\z/file7.txt", "file7.txt" },
- { "037", "attachment; filename=x/y\\z/\\x/file8.txt", "file8.txt" },
- { "038", "attachment; filename=/root/file9.txt", "file9.txt" },
- { "039", "attachment; filename=../file10.txt", "file10.txt" },
- { "040", "attachment; filename=..\\file11.txt", "file11.txt" },
- { "041", "attachment; filename=foo/../../file12.txt", "file12.txt" },
+ { "030", "attachment; filename=\"foo/file1.txt\"", "file1.txt" },
+ { "031", "attachment; filename=\"foo/bar/file2.txt\"", "file2.txt" },
+ { "032", "attachment; filename=\"baz\\\\file3.txt\"", "file3.txt" },
+ { "033", "attachment; filename=\"baz\\\\bar\\\\file4.txt\"", "file4.txt" },
+ { "034", "attachment; filename=\"x/y\\\\file5.txt\"", "file5.txt" },
+ { "035", "attachment; filename=\"x/y\\\\file6.txt\"", "file6.txt" },
+ { "036", "attachment; filename=\"x/y\\\\z/file7.txt\"", "file7.txt" },
+ { "037", "attachment; filename=\"x/y\\\\z/\\\\x/file8.txt\"", "file8.txt" },
+ { "038", "attachment; filename=\"/root/file9.txt\"", "file9.txt" },
+ { "039", "attachment; filename=\"../file10.txt\"", "file10.txt" },
+ { "040", "attachment; filename=\"..\\\\file11.txt\"", "file11.txt" },
+ { "041", "attachment; filename=\"foo/../../file12.txt\"", "file12.txt" },
};
@DataProvider(name = "positive")
@@ -177,18 +177,24 @@ void test(String uriString, String contentDispositionValue, String expectedFilen
CREATE, TRUNCATE_EXISTING, WRITE);
HttpResponse response = client.send(request, bh);
+ Path body = response.body();
out.println("Got response: " + response);
- out.println("Got body Path: " + response.body());
+ out.println("Got body Path: " + body);
String fileContents = new String(Files.readAllBytes(response.body()), UTF_8);
out.println("Got body: " + fileContents);
assertEquals(response.statusCode(),200);
- assertEquals(response.body().getFileName().toString(), expectedFilename);
+ assertEquals(body.getFileName().toString(), expectedFilename);
assertTrue(response.headers().firstValue("Content-Disposition").isPresent());
assertEquals(response.headers().firstValue("Content-Disposition").get(),
contentDispositionValue);
assertEquals(fileContents, "May the luck of the Irish be with you!");
+ if (!body.toAbsolutePath().startsWith(tempDir.toAbsolutePath())) {
+ System.out.println("Tempdir = " + tempDir.toAbsolutePath());
+ System.out.println("body = " + body.toAbsolutePath());
+ throw new AssertionError("body in wrong location");
+ }
// additional checks unrelated to file download
caseInsensitivityOfHeaders(request.headers());
caseInsensitivityOfHeaders(response.headers());
diff --git a/test/jdk/java/util/zip/TestExtraTime.java b/test/jdk/java/util/zip/TestExtraTime.java
index a60e810df0f..0e68e764546 100644
--- a/test/jdk/java/util/zip/TestExtraTime.java
+++ b/test/jdk/java/util/zip/TestExtraTime.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,8 @@
*/
import java.io.*;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -59,7 +61,14 @@ public static void main(String[] args) throws Throwable{
TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
- for (byte[] extra : new byte[][] { null, new byte[] {1, 2, 3}}) {
+ // A structurally valid extra data example
+ byte[] sampleExtra = new byte[Short.BYTES*3];
+ ByteBuffer.wrap(sampleExtra).order(ByteOrder.LITTLE_ENDIAN)
+ .putShort((short) 123) // ID: 123
+ .putShort((short) Short.BYTES) // Size: 2
+ .putShort((short) 42); // Data: Two bytes
+
+ for (byte[] extra : new byte[][] { null, sampleExtra}) {
// ms-dos 1980 epoch problem
test0(FileTime.from(10, TimeUnit.MILLISECONDS), null, null, null, extra);
diff --git a/test/jdk/java/util/zip/ZipFile/CorruptedZipFiles.java b/test/jdk/java/util/zip/ZipFile/CorruptedZipFiles.java
index 6ef3ec5d8f6..b969ecfd04e 100644
--- a/test/jdk/java/util/zip/ZipFile/CorruptedZipFiles.java
+++ b/test/jdk/java/util/zip/ZipFile/CorruptedZipFiles.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -114,13 +114,13 @@ public static void main(String[] args) throws Exception {
err.println("corrupted CENEXT 1");
bad = good.clone();
bad[cenpos+CENEXT]++;
- checkZipException(bad, ".*bad header size.*");
+ checkZipException(bad, ".*invalid zip64 extra data field size.*");
err.println("corrupted CENEXT 2");
bad = good.clone();
bad[cenpos+CENEXT] = (byte)0xfd;
bad[cenpos+CENEXT+1] = (byte)0xfd;
- checkZipException(bad, ".*bad header size.*");
+ checkZipException(bad, ".*extra data field size too long.*");
err.println("corrupted CENCOM");
bad = good.clone();
diff --git a/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java b/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java
index fa6f12bc2b7..58c3c4a0d3b 100644
--- a/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java
+++ b/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,17 +23,24 @@
/*
* @test
- * @bug 8164879
+ * @bug 8164879 8300285
* @library ../../
* @library /test/lib
- * @summary Verify AES/GCM's limits set in the jdk.tls.keyLimits property
+ * @summary Verify AEAD TLS cipher suite limits set in the jdk.tls.keyLimits
+ * property
* start a new handshake sequence to renegotiate the symmetric key with an
* SSLSocket connection. This test verifies the handshake method was called
* via debugging info. It does not verify the renegotiation was successful
* as that is very hard.
*
- * @run main SSLEngineKeyLimit 0 server AES/GCM/NoPadding keyupdate 1050000
- * @run main SSLEngineKeyLimit 1 client AES/GCM/NoPadding keyupdate 2^22
+ * @run main SSLEngineKeyLimit 0 server TLS_AES_256_GCM_SHA384
+ * AES/GCM/NoPadding keyupdate 1050000
+ * @run main SSLEngineKeyLimit 1 client TLS_AES_256_GCM_SHA384
+ * AES/GCM/NoPadding keyupdate 2^22
+ * @run main SSLEngineKeyLimit 0 server TLS_CHACHA20_POLY1305_SHA256
+ * AES/GCM/NoPadding keyupdate 1050000, ChaCha20-Poly1305 KeyUpdate 1050000
+ * @run main SSLEngineKeyLimit 1 client TLS_CHACHA20_POLY1305_SHA256
+ * AES/GCM/NoPadding keyupdate 2^22, ChaCha20-Poly1305 KeyUpdate 2^22
*/
/*
@@ -86,7 +93,7 @@ public class SSLEngineKeyLimit {
}
/**
- * args should have two values: server|client,
+ * args should have two values: server|client, cipher suite,
* Prepending 'p' is for internal use only.
*/
public static void main(String args[]) throws Exception {
@@ -105,7 +112,7 @@ public static void main(String args[]) throws Exception {
File f = new File("keyusage."+ System.nanoTime());
PrintWriter p = new PrintWriter(f);
p.write("jdk.tls.keyLimits=");
- for (int i = 2; i < args.length; i++) {
+ for (int i = 3; i < args.length; i++) {
p.write(" "+ args[i]);
}
p.close();
@@ -120,10 +127,13 @@ public static void main(String args[]) throws Exception {
System.getProperty("test.java.opts"));
ProcessBuilder pb = ProcessTools.createTestJvm(
- Utils.addTestJavaOpts("SSLEngineKeyLimit", "p", args[1]));
+ Utils.addTestJavaOpts("SSLEngineKeyLimit", "p", args[1],
+ args[2]));
OutputAnalyzer output = ProcessTools.executeProcess(pb);
try {
+ output.shouldContain(String.format(
+ "\"cipher suite\" : \"%s", args[2]));
if (expectedFail) {
output.shouldNotContain("KeyUpdate: write key updated");
output.shouldNotContain("KeyUpdate: read key updated");
@@ -171,9 +181,10 @@ public static void main(String args[]) throws Exception {
cTos.clear();
sToc.clear();
- Thread ts = new Thread(serverwrite ? new Client() : new Server());
+ Thread ts = new Thread(serverwrite ? new Client() :
+ new Server(args[2]));
ts.start();
- (serverwrite ? new Server() : new Client()).run();
+ (serverwrite ? new Server(args[2]) : new Client()).run();
ts.interrupt();
ts.join();
}
@@ -417,11 +428,14 @@ SSLContext initContext() throws Exception {
}
static class Server extends SSLEngineKeyLimit implements Runnable {
- Server() throws Exception {
+ Server(String cipherSuite) throws Exception {
super();
eng = initContext().createSSLEngine();
eng.setUseClientMode(false);
eng.setNeedClientAuth(true);
+ if (cipherSuite != null && cipherSuite.length() > 0) {
+ eng.setEnabledCipherSuites(new String[] { cipherSuite });
+ }
}
public void run() {
diff --git a/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java b/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java
index 198e0bdd6f0..8b19d39af7e 100644
--- a/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java
+++ b/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,14 +23,24 @@
/*
* @test
- * @bug 8164879
+ * @bug 8164879 8300285
* @library ../../
* @library /test/lib
* @modules java.base/sun.security.util
- * @summary Verify AES/GCM's limits set in the jdk.tls.keyLimits property
- * @run main SSLSocketKeyLimit 0 server AES/GCM/NoPadding keyupdate 1000000
- * @run main SSLSocketKeyLimit 0 client AES/GCM/NoPadding keyupdate 1000000
- * @run main SSLSocketKeyLimit 1 client AES/GCM/NoPadding keyupdate 2^22
+ * @summary Verify AEAD TLS cipher suite limits set in the jdk.tls.keyLimits
+ * property
+ * @run main SSLSocketKeyLimit 0 server TLS_AES_256_GCM_SHA384
+ * AES/GCM/NoPadding keyupdate 1000000
+ * @run main SSLSocketKeyLimit 0 client TLS_AES_256_GCM_SHA384
+ * AES/GCM/NoPadding keyupdate 1000000
+ * @run main SSLSocketKeyLimit 1 client TLS_AES_256_GCM_SHA384
+ * AES/GCM/NoPadding keyupdate 2^22
+ * @run main SSLSocketKeyLimit 0 server TLS_CHACHA20_POLY1305_SHA256
+ * AES/GCM/NoPadding keyupdate 1000000, ChaCha20-Poly1305 KeyUpdate 1000000
+ * @run main SSLSocketKeyLimit 0 client TLS_CHACHA20_POLY1305_SHA256
+ * AES/GCM/NoPadding keyupdate 1000000, ChaCha20-Poly1305 KeyUpdate 1000000
+ * @run main SSLSocketKeyLimit 1 client TLS_CHACHA20_POLY1305_SHA256
+ * AES/GCM/NoPadding keyupdate 2^22, ChaCha20-Poly1305 KeyUpdate 2^22
*/
/**
@@ -96,7 +106,7 @@ SSLContext initContext() throws Exception {
}
/**
- * args should have two values: server|client,
+ * args should have three values: server|client, cipher suite,
* Prepending 'p' is for internal use only.
*/
public static void main(String args[]) throws Exception {
@@ -110,7 +120,7 @@ public static void main(String args[]) throws Exception {
File f = new File("keyusage."+ System.nanoTime());
PrintWriter p = new PrintWriter(f);
p.write("jdk.tls.keyLimits=");
- for (int i = 2; i < args.length; i++) {
+ for (int i = 3; i < args.length; i++) {
p.write(" "+ args[i]);
}
p.close();
@@ -125,10 +135,13 @@ public static void main(String args[]) throws Exception {
System.getProperty("test.java.opts"));
ProcessBuilder pb = ProcessTools.createTestJvm(
- Utils.addTestJavaOpts("SSLSocketKeyLimit", "p", args[1]));
+ Utils.addTestJavaOpts("SSLSocketKeyLimit", "p", args[1],
+ args[2]));
OutputAnalyzer output = ProcessTools.executeProcess(pb);
try {
+ output.shouldContain(String.format(
+ "\"cipher suite\" : \"%s", args[2]));
if (expectedFail) {
output.shouldNotContain("KeyUpdate: write key updated");
output.shouldNotContain("KeyUpdate: read key updated");
@@ -150,7 +163,7 @@ public static void main(String args[]) throws Exception {
return;
}
- if (args.length > 0 && args[0].compareToIgnoreCase("client") == 0) {
+ if (args.length > 0 && args[1].compareToIgnoreCase("client") == 0) {
serverwrite = false;
}
@@ -162,7 +175,7 @@ public static void main(String args[]) throws Exception {
System.setProperty("javax.net.ssl.keyStorePassword", passwd);
Arrays.fill(data, (byte)0x0A);
- Thread ts = new Thread(new Server());
+ Thread ts = new Thread(new Server(args[2]));
ts.start();
while (!serverReady) {
@@ -200,7 +213,8 @@ void read(SSLSocket s) throws Exception {
int len;
byte i = 0;
try {
- System.out.println("Server: connected " + s.getSession().getCipherSuite());
+ System.out.println("Server: connected " +
+ s.getSession().getCipherSuite());
in = s.getInputStream();
out = s.getOutputStream();
while (true) {
@@ -212,7 +226,8 @@ void read(SSLSocket s) throws Exception {
if (b == 0x0A || b == 0x0D) {
continue;
}
- System.out.println("\nData invalid: " + HexPrinter.minimal().toString(buf));
+ System.out.println("\nData invalid: " +
+ HexPrinter.minimal().toString(buf));
break;
}
@@ -237,11 +252,14 @@ void read(SSLSocket s) throws Exception {
static class Server extends SSLSocketKeyLimit implements Runnable {
private SSLServerSocketFactory ssf;
private SSLServerSocket ss;
- Server() {
+ Server(String cipherSuite) {
super();
try {
ssf = initContext().getServerSocketFactory();
ss = (SSLServerSocket) ssf.createServerSocket(serverPort);
+ if (cipherSuite != null && cipherSuite.length() > 0) {
+ ss.setEnabledCipherSuites(new String[] { cipherSuite });
+ }
serverPort = ss.getLocalPort();
} catch (Exception e) {
System.out.println("server: " + e.getMessage());