diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf
index c188a694618..2b37ac661cb 100644
--- a/make/conf/version-numbers.conf
+++ b/make/conf/version-numbers.conf
@@ -39,4 +39,4 @@ DEFAULT_VERSION_CLASSFILE_MINOR=0
DEFAULT_VERSION_DOCS_API_SINCE=11
DEFAULT_ACCEPTABLE_BOOT_VERSIONS="16 17"
DEFAULT_JDK_SOURCE_TARGET_VERSION=17
-DEFAULT_PROMOTED_VERSION_PRE=ea
+DEFAULT_PROMOTED_VERSION_PRE=
diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp
index 3f29a72a86d..1e897615eaf 100644
--- a/src/hotspot/share/memory/metaspace.cpp
+++ b/src/hotspot/share/memory/metaspace.cpp
@@ -634,11 +634,13 @@ ReservedSpace Metaspace::reserve_address_space_for_compressed_classes(size_t siz
// (the OS already assigned it for something else), go to the next position, wrapping
// around if necessary, until we exhaust all the items.
os::init_random((int)os::javaTimeNanos());
- r = os::random();
+ r = ABS(os::random()) % len;
+ assert(r >= 0, "must be");
log_info(metaspace)("Randomizing compressed class space: start from %d out of %d locations",
- r % len, len);
+ r, len);
}
for (int i = 0; i < len; i++) {
+ assert((i + r) >= 0, "should never underflow because len is small integer");
address a = list.at((i + r) % len);
ReservedSpace rs(size, Metaspace::reserve_alignment(),
os::vm_page_size(), (char*)a);
diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp
index 2ee1e5f52f7..f81e80fec0e 100644
--- a/src/hotspot/share/opto/memnode.cpp
+++ b/src/hotspot/share/opto/memnode.cpp
@@ -579,8 +579,13 @@ Node* LoadNode::find_previous_arraycopy(PhaseTransform* phase, Node* ld_alloc, N
Node* dest = ac->in(ArrayCopyNode::Dest);
if (dest == ld_base) {
- const TypeX *ld_offs_t = phase->type(ld_offs)->isa_intptr_t();
- if (ac->modifies(ld_offs_t->_lo, ld_offs_t->_hi, phase, can_see_stored_value)) {
+ const TypeX* ld_offs_t = phase->type(ld_offs)->isa_intptr_t();
+ assert(!ld_offs_t->empty(), "dead reference should be checked already");
+ // Take into account vector or unsafe access size
+ jlong ld_size_in_bytes = (jlong)memory_size();
+ jlong offset_hi = ld_offs_t->_hi + ld_size_in_bytes - 1;
+ offset_hi = MIN2(offset_hi, (jlong)(TypeX::MAX->_hi)); // Take care for overflow in 32-bit VM
+ if (ac->modifies(ld_offs_t->_lo, (intptr_t)offset_hi, phase, can_see_stored_value)) {
return ac;
}
if (!can_see_stored_value) {
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DESKey.java b/src/java.base/share/classes/com/sun/crypto/provider/DESKey.java
index 21e7247e87b..daea2659f63 100644
--- a/src/java.base/share/classes/com/sun/crypto/provider/DESKey.java
+++ b/src/java.base/share/classes/com/sun/crypto/provider/DESKey.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
@@ -25,6 +25,8 @@
package com.sun.crypto.provider;
+import java.io.IOException;
+import java.io.InvalidObjectException;
import java.lang.ref.Reference;
import java.security.MessageDigest;
import java.security.KeyRep;
@@ -44,7 +46,7 @@
final class DESKey implements SecretKey {
@java.io.Serial
- static final long serialVersionUID = 7724971015953279128L;
+ private static final long serialVersionUID = 7724971015953279128L;
private byte[] key;
@@ -113,7 +115,7 @@ public int hashCode() {
for (int i = 1; i < this.key.length; i++) {
retval += this.key[i] * i;
}
- return(retval ^= "des".hashCode());
+ return(retval ^ "des".hashCode());
}
public boolean equals(Object obj) {
@@ -134,15 +136,28 @@ public boolean equals(Object obj) {
}
/**
- * readObject is called to restore the state of this key from
- * a stream.
+ * Restores the state of this object from the stream.
+ *
+ * @param s the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
*/
@java.io.Serial
private void readObject(java.io.ObjectInputStream s)
- throws java.io.IOException, ClassNotFoundException
+ throws IOException, ClassNotFoundException
{
s.defaultReadObject();
+ if ((key == null) || (key.length != DESKeySpec.DES_KEY_LEN)) {
+ throw new InvalidObjectException("Wrong key size");
+ }
key = key.clone();
+
+ DESKeyGenerator.setParityBit(key, 0);
+
+ // Use the cleaner to zero the key when no longer referenced
+ final byte[] k = key;
+ CleanerFactory.cleaner().register(this,
+ () -> java.util.Arrays.fill(k, (byte)0x00));
}
/**
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DESedeKey.java b/src/java.base/share/classes/com/sun/crypto/provider/DESedeKey.java
index 2847f305017..031495f27a4 100644
--- a/src/java.base/share/classes/com/sun/crypto/provider/DESedeKey.java
+++ b/src/java.base/share/classes/com/sun/crypto/provider/DESedeKey.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
@@ -25,6 +25,8 @@
package com.sun.crypto.provider;
+import java.io.IOException;
+import java.io.InvalidObjectException;
import java.lang.ref.Reference;
import java.security.MessageDigest;
import java.security.KeyRep;
@@ -44,7 +46,7 @@
final class DESedeKey implements SecretKey {
@java.io.Serial
- static final long serialVersionUID = 2463986565756745178L;
+ private static final long serialVersionUID = 2463986565756745178L;
private byte[] key;
@@ -112,7 +114,7 @@ public int hashCode() {
for (int i = 1; i < this.key.length; i++) {
retval += this.key[i] * i;
}
- return(retval ^= "desede".hashCode());
+ return(retval ^ "desede".hashCode());
}
public boolean equals(Object obj) {
@@ -134,15 +136,30 @@ public boolean equals(Object obj) {
}
/**
- * readObject is called to restore the state of this key from
- * a stream.
+ * Restores the state of this object from the stream.
+ *
+ * @param s the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
*/
@java.io.Serial
private void readObject(java.io.ObjectInputStream s)
- throws java.io.IOException, ClassNotFoundException
+ throws IOException, ClassNotFoundException
{
s.defaultReadObject();
+ if ((key == null) || (key.length != DESedeKeySpec.DES_EDE_KEY_LEN)) {
+ throw new InvalidObjectException("Wrong key size");
+ }
key = key.clone();
+
+ DESKeyGenerator.setParityBit(key, 0);
+ DESKeyGenerator.setParityBit(key, 8);
+ DESKeyGenerator.setParityBit(key, 16);
+
+ // Use the cleaner to zero the key when no longer referenced
+ final byte[] k = key;
+ CleanerFactory.cleaner().register(this,
+ () -> java.util.Arrays.fill(k, (byte)0x00));
}
/**
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DHPrivateKey.java b/src/java.base/share/classes/com/sun/crypto/provider/DHPrivateKey.java
index dcce2c4efa5..b584ac415f7 100644
--- a/src/java.base/share/classes/com/sun/crypto/provider/DHPrivateKey.java
+++ b/src/java.base/share/classes/com/sun/crypto/provider/DHPrivateKey.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
@@ -41,8 +41,6 @@
* algorithm.
*
* @author Jan Luehe
- *
- *
* @see DHPublicKey
* @see java.security.KeyAgreement
*/
@@ -50,7 +48,7 @@ final class DHPrivateKey implements PrivateKey,
javax.crypto.interfaces.DHPrivateKey, Serializable {
@java.io.Serial
- static final long serialVersionUID = 7565477590005668886L;
+ private static final long serialVersionUID = 7565477590005668886L;
// only supported version of PKCS#8 PrivateKeyInfo
private static final BigInteger PKCS8_VERSION = BigInteger.ZERO;
@@ -65,10 +63,10 @@ final class DHPrivateKey implements PrivateKey,
private byte[] encodedKey;
// the prime modulus
- private BigInteger p;
+ private final BigInteger p;
// the base generator
- private BigInteger g;
+ private final BigInteger g;
// the private-value length (optional)
private int l;
@@ -336,4 +334,28 @@ private Object writeReplace() throws java.io.ObjectStreamException {
getFormat(),
encodedKey);
}
+
+ /**
+ * Restores the state of this object from the stream.
+ *
+ * JDK 1.5+ objects use KeyReps instead.
+ *
+ * @param stream the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
+ */
+ @java.io.Serial
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ stream.defaultReadObject();
+ if ((key == null) || (key.length == 0)) {
+ throw new InvalidObjectException("key not deserializable");
+ }
+ this.key = key.clone();
+ if ((encodedKey == null) || (encodedKey.length == 0)) {
+ throw new InvalidObjectException(
+ "encoded key not deserializable");
+ }
+ this.encodedKey = encodedKey.clone();
+ }
}
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DHPublicKey.java b/src/java.base/share/classes/com/sun/crypto/provider/DHPublicKey.java
index bf33173ff2e..622aa2a512d 100644
--- a/src/java.base/share/classes/com/sun/crypto/provider/DHPublicKey.java
+++ b/src/java.base/share/classes/com/sun/crypto/provider/DHPublicKey.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2020, 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
@@ -40,8 +40,6 @@
* A public key in X.509 format for the Diffie-Hellman key agreement algorithm.
*
* @author Jan Luehe
- *
- *
* @see DHPrivateKey
* @see javax.crypto.KeyAgreement
*/
@@ -49,7 +47,7 @@ final class DHPublicKey implements PublicKey,
javax.crypto.interfaces.DHPublicKey, Serializable {
@java.io.Serial
- static final long serialVersionUID = 7647557958927458271L;
+ private static final long serialVersionUID = 7647557958927458271L;
// the public key
private BigInteger y;
@@ -61,10 +59,10 @@ final class DHPublicKey implements PublicKey,
private byte[] encodedKey;
// the prime modulus
- private BigInteger p;
+ private final BigInteger p;
// the base generator
- private BigInteger g;
+ private final BigInteger g;
// the private-value length (optional)
private int l;
@@ -324,4 +322,28 @@ private Object writeReplace() throws java.io.ObjectStreamException {
getFormat(),
getEncoded());
}
+
+ /**
+ * Restores the state of this object from the stream.
+ *
+ * JDK 1.5+ objects use KeyReps instead.
+ *
+ * @param stream the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
+ */
+ @java.io.Serial
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ stream.defaultReadObject();
+ if ((key == null) || (key.length == 0)) {
+ throw new InvalidObjectException("key not deserializable");
+ }
+ this.key = key.clone();
+ if ((encodedKey == null) || (encodedKey.length == 0)) {
+ throw new InvalidObjectException(
+ "encoded key not deserializable");
+ }
+ this.encodedKey = encodedKey.clone();
+ }
}
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java b/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java
index 15c9c1f3d59..67efe74f858 100644
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.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
@@ -25,6 +25,8 @@
package com.sun.crypto.provider;
+import java.io.IOException;
+import java.io.InvalidObjectException;
import java.lang.ref.Reference;
import java.security.MessageDigest;
import java.security.KeyRep;
@@ -45,11 +47,11 @@
final class PBEKey implements SecretKey {
@java.io.Serial
- static final long serialVersionUID = -2234768909660948176L;
+ private static final long serialVersionUID = -2234768909660948176L;
private byte[] key;
- private String type;
+ private final String type;
/**
* Creates a PBE key from a given PBE key specification.
@@ -110,7 +112,7 @@ public int hashCode() {
for (int i = 1; i < this.key.length; i++) {
retval += this.key[i] * i;
}
- return(retval ^= getAlgorithm().toLowerCase(Locale.ENGLISH).hashCode());
+ return(retval ^ getAlgorithm().toLowerCase(Locale.ENGLISH).hashCode());
}
public boolean equals(Object obj) {
@@ -144,15 +146,38 @@ public void destroy() {
}
/**
- * readObject is called to restore the state of this key from
- * a stream.
+ * Restores the state of this object from the stream.
+ *
+ * @param s the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
*/
@java.io.Serial
private void readObject(java.io.ObjectInputStream s)
- throws java.io.IOException, ClassNotFoundException
+ throws IOException, ClassNotFoundException
{
s.defaultReadObject();
+ if (key == null) {
+ throw new InvalidObjectException(
+ "PBEKey couldn't be deserialized");
+ }
key = key.clone();
+
+ // Accept "\0" to signify "zero-length password with no terminator".
+ if (!(key.length == 1 && key[0] == 0)) {
+ for (int i = 0; i < key.length; i++) {
+ if ((key[i] < '\u0020') || (key[i] > '\u007E')) {
+ throw new InvalidObjectException(
+ "PBEKey had non-ASCII chars");
+ }
+ }
+ }
+
+ // Use the cleaner to zero the key when no longer referenced
+ final byte[] k = this.key;
+ CleanerFactory.cleaner().register(this,
+ () -> Arrays.fill(k, (byte) 0x00));
+
}
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java b/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java
index 1588385d653..29e331b944a 100644
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java
@@ -25,7 +25,7 @@
package com.sun.crypto.provider;
-import java.io.ObjectStreamException;
+import java.io.*;
import java.lang.ref.Reference;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
@@ -57,14 +57,14 @@
final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
@java.io.Serial
- static final long serialVersionUID = -2234868909660948157L;
+ private static final long serialVersionUID = -2234868909660948157L;
- private char[] passwd;
- private byte[] salt;
- private int iterCount;
+ private final char[] passwd;
+ private final byte[] salt;
+ private final int iterCount;
private byte[] key;
- private Mac prf;
+ private final Mac prf;
private static byte[] getPasswordBytes(char[] passwd) {
CharBuffer cb = CharBuffer.wrap(passwd);
@@ -146,13 +146,14 @@ private static byte[] deriveKey(final Mac prf, final byte[] password,
int intR = keyLength - (intL - 1)*hlen; // residue
byte[] ui = new byte[hlen];
byte[] ti = new byte[hlen];
+ String algName = prf.getAlgorithm();
// SecretKeySpec cannot be used, since password can be empty here.
SecretKey macKey = new SecretKey() {
@java.io.Serial
private static final long serialVersionUID = 7874493593505141603L;
@Override
public String getAlgorithm() {
- return prf.getAlgorithm();
+ return algName;
}
@Override
public String getFormat() {
@@ -165,18 +166,27 @@ public byte[] getEncoded() {
@Override
public int hashCode() {
return Arrays.hashCode(password) * 41 +
- prf.getAlgorithm().toLowerCase(Locale.ENGLISH).hashCode();
+ algName.toLowerCase(Locale.ENGLISH).hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (this.getClass() != obj.getClass()) return false;
SecretKey sk = (SecretKey)obj;
- return prf.getAlgorithm().equalsIgnoreCase(
+ return algName.equalsIgnoreCase(
sk.getAlgorithm()) &&
MessageDigest.isEqual(password, sk.getEncoded());
}
+ // This derived key can't be deserialized.
+ @java.io.Serial
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ throw new InvalidObjectException(
+ "PBKDF2KeyImpl SecretKeys are not " +
+ "directly deserializable");
+ }
};
+
prf.init(macKey);
byte[] ibytes = new byte[4];
@@ -290,4 +300,20 @@ private Object writeReplace() throws ObjectStreamException {
return new KeyRep(KeyRep.Type.SECRET, getAlgorithm(),
getFormat(), key);
}
+
+ /**
+ * Restores the state of this object from the stream.
+ *
+ * Deserialization of this class is not supported.
+ *
+ * @param stream the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
+ */
+ @java.io.Serial
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ throw new InvalidObjectException(
+ "PBKDF2KeyImpl keys are not directly deserializable");
+ }
}
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java b/src/java.base/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java
index c533506b05f..09ab8143bdd 100644
--- a/src/java.base/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java
+++ b/src/java.base/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2021, 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
@@ -25,6 +25,9 @@
package com.sun.crypto.provider;
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
@@ -62,11 +65,11 @@ protected void engineInit(SecureRandom random) {
@SuppressWarnings("deprecation")
protected void engineInit(AlgorithmParameterSpec params,
SecureRandom random) throws InvalidAlgorithmParameterException {
- if (params instanceof TlsMasterSecretParameterSpec == false) {
+ if (!(params instanceof TlsMasterSecretParameterSpec)) {
throw new InvalidAlgorithmParameterException(MSG);
}
this.spec = (TlsMasterSecretParameterSpec)params;
- if ("RAW".equals(spec.getPremasterSecret().getFormat()) == false) {
+ if (!"RAW".equals(spec.getPremasterSecret().getFormat())) {
throw new InvalidAlgorithmParameterException(
"Key format must be RAW");
}
@@ -193,6 +196,22 @@ public byte[] getEncoded() {
return key.clone();
}
- }
+ /**
+ * Restores the state of this object from the stream.
+ *
+ * @param stream the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
+ */
+ @java.io.Serial
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ stream.defaultReadObject();
+ if ((key == null) || (key.length == 0)) {
+ throw new InvalidObjectException("TlsMasterSecretKey is null");
+ }
+ key = key.clone();
+ }
+ }
}
diff --git a/src/java.base/share/classes/java/security/CodeSigner.java b/src/java.base/share/classes/java/security/CodeSigner.java
index 99748210d79..5306d17c8db 100644
--- a/src/java.base/share/classes/java/security/CodeSigner.java
+++ b/src/java.base/share/classes/java/security/CodeSigner.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -156,9 +156,9 @@ public boolean equals(Object obj) {
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("(");
- sb.append("Signer: " + signerCertPath.getCertificates().get(0));
+ sb.append("Signer: ").append(signerCertPath.getCertificates().get(0));
if (timestamp != null) {
- sb.append("timestamp: " + timestamp);
+ sb.append("timestamp: ").append(timestamp);
}
sb.append(")");
return sb.toString();
@@ -174,8 +174,11 @@ public String toString() {
*/
@java.io.Serial
private void readObject(ObjectInputStream ois)
- throws IOException, ClassNotFoundException {
- ois.defaultReadObject();
- myhash = -1;
+ throws IOException, ClassNotFoundException {
+ ois.defaultReadObject();
+ if (signerCertPath == null) {
+ throw new InvalidObjectException("signerCertPath is null");
+ }
+ myhash = -1;
}
}
diff --git a/src/java.base/share/classes/java/security/cert/CertPathHelperImpl.java b/src/java.base/share/classes/java/security/cert/CertPathHelperImpl.java
index bd6545a7357..3da6cb3dd4f 100644
--- a/src/java.base/share/classes/java/security/cert/CertPathHelperImpl.java
+++ b/src/java.base/share/classes/java/security/cert/CertPathHelperImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -25,12 +25,10 @@
package java.security.cert;
-import java.util.*;
+import java.util.Date;
import sun.security.provider.certpath.CertPathHelper;
-import sun.security.x509.GeneralNameInterface;
-
/**
* Helper class that allows the Sun CertPath provider to access
* implementation dependent APIs in CertPath framework.
@@ -55,11 +53,6 @@ static synchronized void initialize() {
}
}
- protected void implSetPathToNames(X509CertSelector sel,
- Set names) {
- sel.setPathToNamesInternal(names);
- }
-
protected void implSetDateAndTime(X509CRLSelector sel, Date date, long skew) {
sel.setDateAndTime(date, skew);
}
diff --git a/src/java.base/share/classes/java/security/cert/X509CertSelector.java b/src/java.base/share/classes/java/security/cert/X509CertSelector.java
index 356e53e21fa..b838b3f51c2 100644
--- a/src/java.base/share/classes/java/security/cert/X509CertSelector.java
+++ b/src/java.base/share/classes/java/security/cert/X509CertSelector.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -87,10 +87,6 @@ public class X509CertSelector implements CertSelector {
private static final ObjectIdentifier ANY_EXTENDED_KEY_USAGE =
ObjectIdentifier.of(KnownOIDs.anyExtendedKeyUsage);
- static {
- CertPathHelperImpl.initialize();
- }
-
private BigInteger serialNumber;
private X500Principal issuer;
private X500Principal subject;
@@ -1159,14 +1155,6 @@ public void setPathToNames(Collection> names) throws IOException {
}
}
- // called from CertPathHelper
- void setPathToNamesInternal(Set names) {
- // set names to non-null dummy value
- // this breaks getPathToNames()
- pathToNames = Collections.>emptySet();
- pathToGeneralNames = names;
- }
-
/**
* Adds a name to the pathToNames criterion. The {@code X509Certificate}
* must not include name constraints that would prohibit building a
diff --git a/src/java.base/share/classes/javax/crypto/spec/SecretKeySpec.java b/src/java.base/share/classes/javax/crypto/spec/SecretKeySpec.java
index 41d4acab748..e691fa9fb66 100644
--- a/src/java.base/share/classes/javax/crypto/spec/SecretKeySpec.java
+++ b/src/java.base/share/classes/javax/crypto/spec/SecretKeySpec.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -28,6 +28,9 @@
import jdk.internal.access.JavaxCryptoSpecAccess;
import jdk.internal.access.SharedSecrets;
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
import java.security.MessageDigest;
import java.security.spec.KeySpec;
import java.util.Arrays;
@@ -259,4 +262,26 @@ public boolean equals(Object obj) {
void clear() {
Arrays.fill(key, (byte)0);
}
+
+ /**
+ * Restores the state of this object from the stream.
+ *
+ * @param stream the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
+ */
+ @java.io.Serial
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ stream.defaultReadObject();
+
+ if (key == null || algorithm == null) {
+ throw new InvalidObjectException("Missing argument");
+ }
+
+ this.key = key.clone();
+ if (key.length == 0) {
+ throw new InvalidObjectException("Invalid key length");
+ }
+ }
}
diff --git a/src/java.base/share/classes/javax/security/auth/callback/ChoiceCallback.java b/src/java.base/share/classes/javax/security/auth/callback/ChoiceCallback.java
index f708df1c812..973d11b1c7e 100644
--- a/src/java.base/share/classes/javax/security/auth/callback/ChoiceCallback.java
+++ b/src/java.base/share/classes/javax/security/auth/callback/ChoiceCallback.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -25,6 +25,10 @@
package javax.security.auth.callback;
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+
/**
*
Underlying security services instantiate and pass a
* {@code ChoiceCallback} to the {@code handle}
@@ -48,7 +52,7 @@ public class ChoiceCallback implements Callback, java.io.Serializable {
* @serial the list of choices
* @since 1.4
*/
- private final String[] choices;
+ private String[] choices;
/**
* @serial the choice to be used as the default choice
* @since 1.4
@@ -72,7 +76,6 @@ public class ChoiceCallback implements Callback, java.io.Serializable {
* a list of choices, a default choice, and a boolean specifying
* whether or not multiple selections from the list of choices are allowed.
*
- *
* @param prompt the prompt used to describe the list of choices.
*
* @param choices the list of choices. The array is cloned to protect
@@ -105,15 +108,15 @@ public ChoiceCallback(String prompt, String[] choices,
defaultChoice < 0 || defaultChoice >= choices.length)
throw new IllegalArgumentException();
+ this.prompt = prompt;
+ this.defaultChoice = defaultChoice;
+ this.multipleSelectionsAllowed = multipleSelectionsAllowed;
+
+ this.choices = choices.clone();
for (int i = 0; i < choices.length; i++) {
if (choices[i] == null || choices[i].isEmpty())
throw new IllegalArgumentException();
}
-
- this.prompt = prompt;
- this.choices = choices.clone();
- this.defaultChoice = defaultChoice;
- this.multipleSelectionsAllowed = multipleSelectionsAllowed;
}
/**
@@ -197,4 +200,38 @@ public void setSelectedIndexes(int[] selections) {
public int[] getSelectedIndexes() {
return selections == null ? null : selections.clone();
}
+
+ /**
+ * Restores the state of this object from the stream.
+ *
+ * @param stream the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
+ */
+ @java.io.Serial
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ stream.defaultReadObject();
+
+ if ((prompt == null) || prompt.isEmpty() ||
+ (choices == null) || (choices.length == 0) ||
+ (defaultChoice < 0) || (defaultChoice >= choices.length)) {
+ throw new InvalidObjectException(
+ "Missing/invalid prompt/choices");
+ }
+
+ choices = choices.clone();
+ for (int i = 0; i < choices.length; i++) {
+ if ((choices[i] == null) || choices[i].isEmpty())
+ throw new InvalidObjectException("Null/empty choices");
+ }
+
+ if (selections != null) {
+ selections = selections.clone();
+ if (!multipleSelectionsAllowed && (selections.length != 1)) {
+ throw new InvalidObjectException(
+ "Multiple selections not allowed");
+ }
+ }
+ }
}
diff --git a/src/java.base/share/classes/javax/security/auth/callback/ConfirmationCallback.java b/src/java.base/share/classes/javax/security/auth/callback/ConfirmationCallback.java
index 926a3d889e2..437ce7041a7 100644
--- a/src/java.base/share/classes/javax/security/auth/callback/ConfirmationCallback.java
+++ b/src/java.base/share/classes/javax/security/auth/callback/ConfirmationCallback.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -25,6 +25,9 @@
package javax.security.auth.callback;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+
/**
*
Underlying security services instantiate and pass a
* {@code ConfirmationCallback} to the {@code handle}
@@ -147,7 +150,7 @@ public class ConfirmationCallback implements Callback, java.io.Serializable {
* @serial
* @since 1.4
*/
- private final String[] options;
+ private String[] options;
/**
* @serial
* @since 1.4
@@ -252,16 +255,16 @@ public ConfirmationCallback(int messageType,
defaultOption < 0 || defaultOption >= options.length)
throw new IllegalArgumentException();
- for (int i = 0; i < options.length; i++) {
- if (options[i] == null || options[i].isEmpty())
- throw new IllegalArgumentException();
- }
-
this.prompt = null;
this.messageType = messageType;
this.optionType = UNSPECIFIED_OPTION;
- this.options = options.clone();
this.defaultOption = defaultOption;
+
+ this.options = options.clone();
+ for (int i = 0; i < options.length; i++) {
+ if (options[i] == null || options[i].isEmpty())
+ throw new IllegalArgumentException();
+ }
}
/**
@@ -372,16 +375,16 @@ public ConfirmationCallback(String prompt, int messageType,
defaultOption < 0 || defaultOption >= options.length)
throw new IllegalArgumentException();
- for (int i = 0; i < options.length; i++) {
- if (options[i] == null || options[i].isEmpty())
- throw new IllegalArgumentException();
- }
-
this.prompt = prompt;
this.messageType = messageType;
this.optionType = UNSPECIFIED_OPTION;
- this.options = options.clone();
this.defaultOption = defaultOption;
+
+ this.options = options.clone();
+ for (int i = 0; i < options.length; i++) {
+ if (options[i] == null || options[i].isEmpty())
+ throw new IllegalArgumentException();
+ }
}
/**
@@ -487,4 +490,20 @@ public void setSelectedIndex(int selection) {
public int getSelectedIndex() {
return selection;
}
+
+ /**
+ * Restores the state of this object from the stream.
+ *
+ * @param stream the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
+ */
+ @java.io.Serial
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ stream.defaultReadObject();
+ if (options != null) {
+ options = options.clone();
+ }
+ }
}
diff --git a/src/java.base/share/classes/javax/security/auth/callback/PasswordCallback.java b/src/java.base/share/classes/javax/security/auth/callback/PasswordCallback.java
index 36a54b79958..5e0f6bb5fde 100644
--- a/src/java.base/share/classes/javax/security/auth/callback/PasswordCallback.java
+++ b/src/java.base/share/classes/javax/security/auth/callback/PasswordCallback.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -25,6 +25,15 @@
package javax.security.auth.callback;
+import java.lang.ref.Cleaner;
+import java.util.Arrays;
+
+import jdk.internal.ref.CleanerFactory;
+
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+
/**
*
Underlying security services instantiate and pass a
* {@code PasswordCallback} to the {@code handle}
@@ -38,16 +47,20 @@ public class PasswordCallback implements Callback, java.io.Serializable {
@java.io.Serial
private static final long serialVersionUID = 2267422647454909926L;
+ private transient Cleaner.Cleanable cleanable;
+
/**
* @serial
* @since 1.4
*/
- private String prompt;
+ private final String prompt;
+
/**
* @serial
* @since 1.4
*/
- private boolean echoOn;
+ private final boolean echoOn;
+
/**
* @serial
* @since 1.4
@@ -106,7 +119,19 @@ public boolean isEchoOn() {
* @see #getPassword
*/
public void setPassword(char[] password) {
+ // Cleanup the last buffered password copy.
+ if (cleanable != null) {
+ cleanable.clean();
+ cleanable = null;
+ }
+
+ // Set the retrieved password.
this.inputPassword = (password == null ? null : password.clone());
+
+ if (this.inputPassword != null) {
+ cleanable = CleanerFactory.cleaner().register(
+ this, cleanerFor(inputPassword));
+ }
}
/**
@@ -126,9 +151,39 @@ public char[] getPassword() {
* Clear the retrieved password.
*/
public void clearPassword() {
+ // Cleanup the last retrieved password copy.
+ if (cleanable != null) {
+ cleanable.clean();
+ cleanable = null;
+ }
+ }
+
+ private static Runnable cleanerFor(char[] password) {
+ return () -> {
+ Arrays.fill(password, ' ');
+ };
+ }
+
+ /**
+ * Restores the state of this object from the stream.
+ *
+ * @param stream the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
+ */
+ @java.io.Serial
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ stream.defaultReadObject();
+
+ if (prompt == null || prompt.isEmpty()) {
+ throw new InvalidObjectException("Missing prompt");
+ }
+
if (inputPassword != null) {
- for (int i = 0; i < inputPassword.length; i++)
- inputPassword[i] = ' ';
+ inputPassword = inputPassword.clone();
+ cleanable = CleanerFactory.cleaner().register(
+ this, cleanerFor(inputPassword));
}
}
}
diff --git a/src/java.base/share/classes/jdk/internal/icu/text/BidiBase.java b/src/java.base/share/classes/jdk/internal/icu/text/BidiBase.java
index 1714c15143a..ae834f06584 100644
--- a/src/java.base/share/classes/jdk/internal/icu/text/BidiBase.java
+++ b/src/java.base/share/classes/jdk/internal/icu/text/BidiBase.java
@@ -4595,7 +4595,7 @@ public static void reorderVisually(byte[] levels,
objectStart + " is out of range 0 to " +
(objects.length-1));
}
- if (0 > count || objects.length < (objectStart+count)) {
+ if (0 > count || objects.length - count < objectStart) {
throw new IllegalArgumentException("Value count " +
count + " is less than zero, or objectStart + count" +
" is beyond objects length " + objects.length);
diff --git a/src/java.base/share/classes/sun/security/provider/DSAPublicKeyImpl.java b/src/java.base/share/classes/sun/security/provider/DSAPublicKeyImpl.java
index 2c402ef2863..ca84d202c14 100644
--- a/src/java.base/share/classes/sun/security/provider/DSAPublicKeyImpl.java
+++ b/src/java.base/share/classes/sun/security/provider/DSAPublicKeyImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2019, 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
@@ -25,17 +25,20 @@
package sun.security.provider;
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
import java.math.BigInteger;
import java.security.KeyRep;
import java.security.InvalidKeyException;
/**
* An X.509 public key for the Digital Signature Algorithm.
- *
+ *
* The difference between DSAPublicKeyImpl and DSAPublicKey is that
* DSAPublicKeyImpl calls writeReplace with KeyRep, and DSAPublicKey
* calls writeObject.
- *
+ *
* See the comments in DSAKeyFactory, 4532506, and 6232513.
*
*/
@@ -72,10 +75,26 @@ public DSAPublicKeyImpl(byte[] encoded) throws InvalidKeyException {
}
@java.io.Serial
- protected Object writeReplace() throws java.io.ObjectStreamException {
+ private Object writeReplace() throws java.io.ObjectStreamException {
return new KeyRep(KeyRep.Type.PUBLIC,
getAlgorithm(),
getFormat(),
getEncoded());
}
+
+ /**
+ * Restores the state of this object from the stream.
+ *
+ * Deserialization of this object is not supported.
+ *
+ * @param stream the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
+ */
+ @java.io.Serial
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ throw new InvalidObjectException(
+ "DSAPublicKeyImpl keys are not directly deserializable");
+ }
}
diff --git a/src/java.base/share/classes/sun/security/provider/PolicyFile.java b/src/java.base/share/classes/sun/security/provider/PolicyFile.java
index a9be95dd598..3dfc12ac377 100644
--- a/src/java.base/share/classes/sun/security/provider/PolicyFile.java
+++ b/src/java.base/share/classes/sun/security/provider/PolicyFile.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
@@ -2097,8 +2097,17 @@ public SelfPermission(String type, String name, String actions,
this.actions.equals(that.actions)))
return false;
- if (this.certs.length != that.certs.length)
+ if ((this.certs == null) && (that.certs == null)) {
+ return true;
+ }
+
+ if ((this.certs == null) || (that.certs == null)) {
+ return false;
+ }
+
+ if (this.certs.length != that.certs.length) {
return false;
+ }
int i,j;
boolean match;
@@ -2168,7 +2177,7 @@ public String getSelfActions() {
}
public Certificate[] getCerts() {
- return certs;
+ return (certs == null ? null : certs.clone());
}
/**
@@ -2181,6 +2190,22 @@ public Certificate[] getCerts() {
@Override public String toString() {
return "(SelfPermission " + type + " " + name + " " + actions + ")";
}
+
+ /**
+ * Restores the state of this object from the stream.
+ *
+ * @param stream the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
+ */
+ @java.io.Serial
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ stream.defaultReadObject();
+ if (certs != null) {
+ this.certs = certs.clone();
+ }
+ }
}
/**
diff --git a/src/java.base/share/classes/sun/security/provider/SecureRandom.java b/src/java.base/share/classes/sun/security/provider/SecureRandom.java
index 0ccaa81289c..c5e901322fb 100644
--- a/src/java.base/share/classes/sun/security/provider/SecureRandom.java
+++ b/src/java.base/share/classes/sun/security/provider/SecureRandom.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -26,6 +26,7 @@
package sun.security.provider;
import java.io.IOException;
+import java.io.InvalidObjectException;
import java.security.MessageDigest;
import java.security.SecureRandomSpi;
import java.security.NoSuchAlgorithmException;
@@ -193,7 +194,7 @@ private static void updateState(byte[] state, byte[] output) {
/**
* This static object will be seeded by SeedGenerator, and used
* to seed future instances of SHA1PRNG SecureRandoms.
- *
+ *
* Bloch, Effective Java Second Edition: Item 71
*/
private static class SeederHolder {
@@ -268,18 +269,24 @@ public synchronized void engineNextBytes(byte[] result) {
}
/*
- * readObject is called to restore the state of the random object from
- * a stream. We have to create a new instance of MessageDigest, because
+ * This method is called to restore the state of the random object from
+ * a stream.
+ *
+ * We have to create a new instance of {@code MessageDigest}, because
* it is not included in the stream (it is marked "transient").
- *
- * Note that the engineNextBytes() method invoked on the restored random
- * object will yield the exact same (random) bytes as the original.
+ *
+ * Note that the {@code engineNextBytes()} method invoked on the restored
+ * random object will yield the exact same (random) bytes as the original.
* If you do not want this behaviour, you should re-seed the restored
- * random object, using engineSetSeed().
+ * random object, using {@code engineSetSeed()}.
+ *
+ * @param s the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
*/
@java.io.Serial
private void readObject(java.io.ObjectInputStream s)
- throws IOException, ClassNotFoundException {
+ throws IOException, ClassNotFoundException {
s.defaultReadObject ();
@@ -298,5 +305,34 @@ private void readObject(java.io.ObjectInputStream s)
"internal error: SHA-1 not available.", exc);
}
}
+
+ // Various consistency checks
+ if ((remainder == null) && (remCount > 0)) {
+ throw new InvalidObjectException(
+ "Remainder indicated, but no data available");
+ }
+
+ // Not yet allocated state
+ if (state == null) {
+ if (remainder == null) {
+ return;
+ } else {
+ throw new InvalidObjectException(
+ "Inconsistent buffer allocations");
+ }
+ }
+
+ // Sanity check on sizes/pointer
+ if ((state.length != DIGEST_SIZE) ||
+ ((remainder != null) && (remainder.length != DIGEST_SIZE)) ||
+ (remCount < 0 ) || (remCount >= DIGEST_SIZE)) {
+ throw new InvalidObjectException(
+ "Inconsistent buffer sizes/state");
+ }
+
+ state = state.clone();
+ if (remainder != null) {
+ remainder = remainder.clone();
+ }
}
}
diff --git a/src/java.base/share/classes/sun/security/provider/certpath/CertPathHelper.java b/src/java.base/share/classes/sun/security/provider/certpath/CertPathHelper.java
index 7c02007422d..ebc2200f0e6 100644
--- a/src/java.base/share/classes/sun/security/provider/certpath/CertPathHelper.java
+++ b/src/java.base/share/classes/sun/security/provider/certpath/CertPathHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -26,14 +26,10 @@
package sun.security.provider.certpath;
import java.util.Date;
-import java.util.Set;
import java.security.cert.TrustAnchor;
-import java.security.cert.X509CertSelector;
import java.security.cert.X509CRLSelector;
-import sun.security.x509.GeneralNameInterface;
-
/**
* Helper class that allows access to JDK specific known-public methods in the
* java.security.cert package. It relies on a subclass in the
@@ -55,18 +51,10 @@ protected CertPathHelper() {
// empty
}
- protected abstract void implSetPathToNames(X509CertSelector sel,
- Set names);
-
protected abstract void implSetDateAndTime(X509CRLSelector sel, Date date, long skew);
protected abstract boolean implIsJdkCA(TrustAnchor anchor);
- static void setPathToNames(X509CertSelector sel,
- Set names) {
- instance.implSetPathToNames(sel, names);
- }
-
public static void setDateAndTime(X509CRLSelector sel, Date date, long skew) {
instance.implSetDateAndTime(sel, date, skew);
}
diff --git a/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java b/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java
index f05a924440b..2fbeb8856ee 100644
--- a/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java
+++ b/src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java
@@ -48,7 +48,6 @@
import sun.security.x509.AuthorityInfoAccessExtension;
import sun.security.x509.AuthorityKeyIdentifierExtension;
import static sun.security.x509.PKIXExtensions.*;
-import sun.security.x509.SubjectAlternativeNameExtension;
import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
@@ -258,14 +257,6 @@ private void getMatchingCACerts(ForwardState currentState,
*/
caSelector.setSubject(currentState.issuerDN);
- /*
- * Match on subjectNamesTraversed (both DNs and AltNames)
- * (checks that current cert's name constraints permit it
- * to certify all the DNs and AltNames that have been traversed)
- */
- CertPathHelper.setPathToNames
- (caSelector, currentState.subjectNamesTraversed);
-
/*
* check the validity period
*/
@@ -704,19 +695,6 @@ void verifyCert(X509Certificate cert, State currentState,
// Don't bother to verify untrusted certificate more.
currState.untrustedChecker.check(cert, Collections.emptySet());
- /*
- * Abort if we encounter the same certificate or a certificate with
- * the same public key, subject DN, and subjectAltNames as a cert
- * that is already in path.
- */
- for (X509Certificate cpListCert : certPathList) {
- if (repeated(cpListCert, cert)) {
- throw new CertPathValidatorException(
- "cert with repeated subject, public key, and " +
- "subjectAltNames detected");
- }
- }
-
/* check if trusted cert */
boolean isTrustedCert = trustedCerts.contains(cert);
@@ -794,49 +772,6 @@ void verifyCert(X509Certificate cert, State currentState,
}
}
- /**
- * Return true if two certificates are equal or have the same subject,
- * public key, and subject alternative names.
- */
- private static boolean repeated(
- X509Certificate currCert, X509Certificate nextCert) {
- if (currCert.equals(nextCert)) {
- return true;
- }
- return (currCert.getSubjectX500Principal().equals(
- nextCert.getSubjectX500Principal()) &&
- currCert.getPublicKey().equals(nextCert.getPublicKey()) &&
- altNamesEqual(currCert, nextCert));
- }
-
- /**
- * Return true if two certificates have the same subject alternative names.
- */
- private static boolean altNamesEqual(
- X509Certificate currCert, X509Certificate nextCert) {
- X509CertImpl curr, next;
- try {
- curr = X509CertImpl.toImpl(currCert);
- next = X509CertImpl.toImpl(nextCert);
- } catch (CertificateException ce) {
- return false;
- }
-
- SubjectAlternativeNameExtension currAltNameExt =
- curr.getSubjectAlternativeNameExtension();
- SubjectAlternativeNameExtension nextAltNameExt =
- next.getSubjectAlternativeNameExtension();
- if (currAltNameExt != null) {
- if (nextAltNameExt == null) {
- return false;
- }
- return Arrays.equals(currAltNameExt.getExtensionValue(),
- nextAltNameExt.getExtensionValue());
- } else {
- return (nextAltNameExt == null);
- }
- }
-
/**
* Verifies whether the input certificate completes the path.
* First checks the cert against each trust anchor that was specified,
diff --git a/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java b/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java
index 9d7af9b169b..9a5088babf2 100644
--- a/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java
+++ b/src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java
@@ -31,17 +31,11 @@
import java.security.cert.PKIXCertPathChecker;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
import java.util.ListIterator;
import javax.security.auth.x500.X500Principal;
import sun.security.util.Debug;
-import sun.security.x509.SubjectAlternativeNameExtension;
-import sun.security.x509.GeneralNames;
-import sun.security.x509.GeneralName;
-import sun.security.x509.GeneralNameInterface;
-import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
/**
@@ -61,9 +55,6 @@ class ForwardState implements State {
/* The last cert in the path */
X509CertImpl cert;
- /* The set of subjectDNs and subjectAltNames of all certs in the path */
- HashSet subjectNamesTraversed;
-
/*
* The number of intermediate CA certs which have been traversed so
* far in the path
@@ -73,7 +64,6 @@ class ForwardState implements State {
/* Flag indicating if state is initial (path is just starting) */
private boolean init = true;
-
/* the untrusted certificates checker */
UntrustedChecker untrustedChecker;
@@ -104,8 +94,6 @@ public String toString() {
sb.append("\n issuerDN of last cert: ").append(issuerDN);
sb.append("\n traversedCACerts: ").append(traversedCACerts);
sb.append("\n init: ").append(String.valueOf(init));
- sb.append("\n subjectNamesTraversed: \n").append
- (subjectNamesTraversed);
sb.append("\n selfIssued: ").append
(String.valueOf(selfIssued));
sb.append("]\n");
@@ -120,7 +108,6 @@ public String toString() {
public void initState(List certPathCheckers)
throws CertPathValidatorException
{
- subjectNamesTraversed = new HashSet();
traversedCACerts = 0;
/*
@@ -170,32 +157,6 @@ public void updateState(X509Certificate cert)
}
}
- /* update subjectNamesTraversed only if this is the EE cert or if
- this cert is not self-issued */
- if (init || !selfIssued) {
- X500Principal subjName = cert.getSubjectX500Principal();
- subjectNamesTraversed.add(X500Name.asX500Name(subjName));
-
- try {
- SubjectAlternativeNameExtension subjAltNameExt
- = icert.getSubjectAlternativeNameExtension();
- if (subjAltNameExt != null) {
- GeneralNames gNames = subjAltNameExt.get(
- SubjectAlternativeNameExtension.SUBJECT_NAME);
- for (GeneralName gName : gNames.names()) {
- subjectNamesTraversed.add(gName.getName());
- }
- }
- } catch (IOException e) {
- if (debug != null) {
- debug.println("ForwardState.updateState() unexpected "
- + "exception");
- e.printStackTrace();
- }
- throw new CertPathValidatorException(e);
- }
- }
-
init = false;
}
@@ -203,10 +164,6 @@ public void updateState(X509Certificate cert)
* Clone current state. The state is cloned as each cert is
* added to the path. This is necessary if backtracking occurs,
* and a prior state needs to be restored.
- *
- * Note that this is a SMART clone. Not all fields are fully copied,
- * because some of them will
- * not have their contents modified by subsequent calls to updateState.
*/
@Override
@SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
@@ -226,13 +183,6 @@ public Object clone() {
}
}
- /*
- * Shallow copy traversed names. There is no need to
- * deep copy contents, since the elements of the Set
- * are never modified by subsequent calls to updateState().
- */
- clonedState.subjectNamesTraversed
- = (HashSet)subjectNamesTraversed.clone();
return clonedState;
} catch (CloneNotSupportedException e) {
throw new InternalError(e.toString(), e);
diff --git a/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java b/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java
index fd4eb9543e9..fd5a01a923d 100644
--- a/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java
+++ b/src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java
@@ -33,6 +33,7 @@
import java.security.cert.CertPathValidatorException.BasicReason;
import java.security.cert.PKIXReason;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -42,6 +43,7 @@
import sun.security.provider.certpath.PKIX.BuilderParams;
import static sun.security.x509.PKIXExtensions.*;
+import sun.security.x509.SubjectAlternativeNameExtension;
import sun.security.x509.X509CertImpl;
import sun.security.util.Debug;
@@ -265,7 +267,7 @@ private void depthFirstSearchForward(X500Principal dN,
*/
Collection certs =
builder.getMatchingCerts(currentState, buildParams.certStores());
- List vertices = addVertices(certs, adjList);
+ List vertices = addVertices(certs, adjList, cpList);
if (debug != null) {
debug.println("SunCertPathBuilder.depthFirstSearchForward(): "
+ "certs.size=" + vertices.size());
@@ -325,17 +327,32 @@ private void depthFirstSearchForward(X500Principal dN,
* cert (which is signed by the trusted public key), but
* don't add it yet to the cpList
*/
+ PublicKey rootKey = cert.getPublicKey();
if (builder.trustAnchor.getTrustedCert() == null) {
appendedCerts.add(0, cert);
+ rootKey = builder.trustAnchor.getCAPublicKey();
+ if (debug != null)
+ debug.println(
+ "SunCertPathBuilder.depthFirstSearchForward " +
+ "using buildParams public key: " +
+ rootKey.toString());
}
+ TrustAnchor anchor = new TrustAnchor
+ (cert.getSubjectX500Principal(), rootKey, null);
+ // add the basic checker
+ List checkers = new ArrayList<>();
+ BasicChecker basicChecker = new BasicChecker(anchor,
+ buildParams.date(),
+ buildParams.sigProvider(),
+ true);
+ checkers.add(basicChecker);
Set initExpPolSet =
Collections.singleton(PolicyChecker.ANY_POLICY);
PolicyNodeImpl rootNode = new PolicyNodeImpl(null,
PolicyChecker.ANY_POLICY, null, false, initExpPolSet, false);
- List checkers = new ArrayList<>();
PolicyChecker policyChecker
= new PolicyChecker(buildParams.initialPolicies(),
appendedCerts.size(),
@@ -346,28 +363,13 @@ private void depthFirstSearchForward(X500Principal dN,
rootNode);
checkers.add(policyChecker);
+ // add the constraints checker
+ checkers.add(new ConstraintsChecker(appendedCerts.size()));
+
// add the algorithm checker
checkers.add(new AlgorithmChecker(builder.trustAnchor,
buildParams.timestamp(), buildParams.variant()));
- PublicKey rootKey = cert.getPublicKey();
- if (builder.trustAnchor.getTrustedCert() == null) {
- rootKey = builder.trustAnchor.getCAPublicKey();
- if (debug != null)
- debug.println(
- "SunCertPathBuilder.depthFirstSearchForward " +
- "using buildParams public key: " +
- rootKey.toString());
- }
- TrustAnchor anchor = new TrustAnchor
- (cert.getSubjectX500Principal(), rootKey, null);
-
- // add the basic checker
- BasicChecker basicChecker = new BasicChecker(anchor,
- buildParams.date(),
- buildParams.sigProvider(),
- true);
- checkers.add(basicChecker);
buildParams.setCertPath(cf.generateCertPath(appendedCerts));
@@ -563,18 +565,79 @@ private void depthFirstSearchForward(X500Principal dN,
* adjacency list.
*/
private static List addVertices(Collection certs,
- List> adjList)
+ List> adjList,
+ List cpList)
{
List l = adjList.get(adjList.size() - 1);
for (X509Certificate cert : certs) {
- Vertex v = new Vertex(cert);
- l.add(v);
+ boolean repeated = false;
+ for (X509Certificate cpListCert : cpList) {
+ /*
+ * Ignore if we encounter the same certificate or a
+ * certificate with the same public key, subject DN, and
+ * subjectAltNames as a cert that is already in path.
+ */
+ if (repeated(cpListCert, cert)) {
+ if (debug != null) {
+ debug.println("cert with repeated subject, " +
+ "public key, and subjectAltNames detected");
+ }
+ repeated = true;
+ break;
+ }
+ }
+ if (!repeated) {
+ l.add(new Vertex(cert));
+ }
}
return l;
}
+ /**
+ * Return true if two certificates are equal or have the same subject,
+ * public key, and subject alternative names.
+ */
+ private static boolean repeated(
+ X509Certificate currCert, X509Certificate nextCert) {
+ if (currCert.equals(nextCert)) {
+ return true;
+ }
+ return (currCert.getSubjectX500Principal().equals(
+ nextCert.getSubjectX500Principal()) &&
+ currCert.getPublicKey().equals(nextCert.getPublicKey()) &&
+ altNamesEqual(currCert, nextCert));
+ }
+
+ /**
+ * Return true if two certificates have the same subject alternative names.
+ */
+ private static boolean altNamesEqual(
+ X509Certificate currCert, X509Certificate nextCert) {
+ X509CertImpl curr, next;
+ try {
+ curr = X509CertImpl.toImpl(currCert);
+ next = X509CertImpl.toImpl(nextCert);
+ } catch (CertificateException ce) {
+ return false;
+ }
+
+ SubjectAlternativeNameExtension currAltNameExt =
+ curr.getSubjectAlternativeNameExtension();
+ SubjectAlternativeNameExtension nextAltNameExt =
+ next.getSubjectAlternativeNameExtension();
+ if (currAltNameExt != null) {
+ if (nextAltNameExt == null) {
+ return false;
+ }
+ return Arrays.equals(currAltNameExt.getExtensionValue(),
+ nextAltNameExt.getExtensionValue());
+ } else {
+ return (nextAltNameExt == null);
+ }
+ }
+
/**
* Returns true if trust anchor certificate matches specified
* certificate constraints.
diff --git a/src/java.base/share/classes/sun/security/provider/certpath/X509CertPath.java b/src/java.base/share/classes/sun/security/provider/certpath/X509CertPath.java
index e8e1e82be8b..d692f592e8d 100644
--- a/src/java.base/share/classes/sun/security/provider/certpath/X509CertPath.java
+++ b/src/java.base/share/classes/sun/security/provider/certpath/X509CertPath.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -25,10 +25,7 @@
package sun.security.provider.certpath;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
+import java.io.*;
import java.security.cert.CertificateEncodingException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
@@ -396,4 +393,20 @@ public Iterator getEncodings() {
public List getCertificates() {
return certs;
}
+
+ /**
+ * Restores the state of this object from the stream.
+ *
+ * Deserialization of this object is not supported.
+ *
+ * @param stream the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
+ */
+ @java.io.Serial
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ throw new InvalidObjectException(
+ "X509CertPaths are not directly deserializable");
+ }
}
diff --git a/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java b/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java
index fbc9fda05fa..4c5af4b953c 100644
--- a/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java
+++ b/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -26,6 +26,8 @@
package sun.security.rsa;
import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
import java.math.BigInteger;
import java.security.*;
@@ -43,7 +45,7 @@
* RSA private key implementation for "RSA", "RSASSA-PSS" algorithms in CRT form.
* For non-CRT private keys, see RSAPrivateKeyImpl. We need separate classes
* to ensure correct behavior in instanceof checks, etc.
- *
+ *
* Note: RSA keys must be at least 512 bits long
*
* @see RSAPrivateKeyImpl
@@ -361,4 +363,20 @@ private void parseKeyBits() throws InvalidKeyException {
throw new InvalidKeyException("Invalid RSA private key", e);
}
}
+
+ /**
+ * Restores the state of this object from the stream.
+ *
+ * Deserialization of this object is not supported.
+ *
+ * @param stream the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
+ */
+ @java.io.Serial
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ throw new InvalidObjectException(
+ "RSAPrivateCrtKeyImpl keys are not directly deserializable");
+ }
}
diff --git a/src/java.base/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java b/src/java.base/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java
index 699a5db6367..5a645c7e887 100644
--- a/src/java.base/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java
+++ b/src/java.base/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -26,6 +26,8 @@
package sun.security.rsa;
import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
import java.math.BigInteger;
import java.security.*;
@@ -40,10 +42,11 @@
/**
* RSA private key implementation for "RSA", "RSASSA-PSS" algorithms in non-CRT
- * form (modulus, private exponent only). For CRT private keys, see
- * RSAPrivateCrtKeyImpl. We need separate classes to ensure correct behavior
- * in instanceof checks, etc.
- *
+ * form (modulus, private exponent only).
+ *
+ * For CRT private keys, see RSAPrivateCrtKeyImpl. We need separate classes
+ * to ensure correct behavior in instanceof checks, etc.
+ *
* Note: RSA keys must be at least 512 bits long
*
* @see RSAPrivateCrtKeyImpl
@@ -147,4 +150,20 @@ public String toString() {
+ " bits" + "\n params: " + keyParams + "\n modulus: " + n
+ "\n private exponent: " + d;
}
+
+ /**
+ * Restores the state of this object from the stream.
+ *
+ * Deserialization of this object is not supported.
+ *
+ * @param stream the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
+ */
+ @java.io.Serial
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ throw new InvalidObjectException(
+ "RSAPrivateKeyImpl keys are not directly deserializable");
+ }
}
diff --git a/src/java.base/share/classes/sun/security/rsa/RSAPublicKeyImpl.java b/src/java.base/share/classes/sun/security/rsa/RSAPublicKeyImpl.java
index d5002c15000..61522cad2fe 100644
--- a/src/java.base/share/classes/sun/security/rsa/RSAPublicKeyImpl.java
+++ b/src/java.base/share/classes/sun/security/rsa/RSAPublicKeyImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -26,6 +26,8 @@
package sun.security.rsa;
import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
import java.math.BigInteger;
import java.security.*;
@@ -39,7 +41,7 @@
/**
* RSA public key implementation for "RSA", "RSASSA-PSS" algorithms.
- *
+ *
* Note: RSA keys must be at least 512 bits long
*
* @see RSAPrivateCrtKeyImpl
@@ -238,10 +240,26 @@ public String toString() {
}
@java.io.Serial
- protected Object writeReplace() throws java.io.ObjectStreamException {
+ private Object writeReplace() throws java.io.ObjectStreamException {
return new KeyRep(KeyRep.Type.PUBLIC,
getAlgorithm(),
getFormat(),
getEncoded());
}
+
+ /**
+ * Restores the state of this object from the stream.
+ *
+ * Deserialization of this object is not supported.
+ *
+ * @param stream the {@code ObjectInputStream} from which data is read
+ * @throws IOException if an I/O error occurs
+ * @throws ClassNotFoundException if a serialized class cannot be loaded
+ */
+ @java.io.Serial
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ throw new InvalidObjectException(
+ "RSAPublicKeyImpl keys are not directly deserializable");
+ }
}
diff --git a/src/java.base/share/classes/sun/security/x509/X509CertImpl.java b/src/java.base/share/classes/sun/security/x509/X509CertImpl.java
index 254016d6a28..5a296bf9494 100644
--- a/src/java.base/share/classes/sun/security/x509/X509CertImpl.java
+++ b/src/java.base/share/classes/sun/security/x509/X509CertImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -25,13 +25,7 @@
package sun.security.x509;
-import java.io.BufferedReader;
-import java.io.BufferedInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
+import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.*;
@@ -629,7 +623,7 @@ public void checkValidity(Date date)
/**
* Return the requested attribute from the certificate.
- *
+ *
* Note that the X509CertInfo is not cloned for performance reasons.
* Callers must ensure that they do not modify it. All other
* attributes are cloned.
@@ -1534,7 +1528,7 @@ private static Collection> makeAltNames(GeneralNames names) {
for (GeneralName gname : names.names()) {
GeneralNameInterface name = gname.getName();
List