8311902: Concurrency regression in the PBKDF2 key impl of SunJCE provider

Reviewed-by: ascarpino, xuelei, mullan
This commit is contained in:
Valerie Peng 2023-07-18 21:35:41 +00:00
parent 5c4623b360
commit 28c4d196cf

View file

@ -26,6 +26,7 @@
package com.sun.crypto.provider; package com.sun.crypto.provider;
import java.io.ObjectStreamException; import java.io.ObjectStreamException;
import java.lang.ref.Reference;
import java.lang.ref.Cleaner; import java.lang.ref.Cleaner;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.CharBuffer; import java.nio.CharBuffer;
@ -205,7 +206,12 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
} }
public byte[] getEncoded() { public byte[] getEncoded() {
try {
return key.clone(); return key.clone();
} finally {
// prevent this from being cleaned for the above block
Reference.reachabilityFence(this);
}
} }
public String getAlgorithm() { public String getAlgorithm() {
@ -221,7 +227,12 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
} }
public char[] getPassword() { public char[] getPassword() {
try {
return passwd.clone(); return passwd.clone();
} finally {
// prevent this from being cleaned for the above block
Reference.reachabilityFence(this);
}
} }
public byte[] getSalt() { public byte[] getSalt() {
@ -237,30 +248,45 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
* Objects that are equal will also have the same hashcode. * Objects that are equal will also have the same hashcode.
*/ */
public int hashCode() { public int hashCode() {
try {
int retval = 0; int retval = 0;
for (int i = 1; i < this.key.length; i++) { for (int i = 1; i < this.key.length; i++) {
retval += this.key[i] * i; retval += this.key[i] * i;
} }
return(retval ^= getAlgorithm().toLowerCase(Locale.ENGLISH).hashCode()); return (retval ^= getAlgorithm().toLowerCase
(Locale.ENGLISH).hashCode());
} finally {
// prevent this from being cleaned for the above block
Reference.reachabilityFence(this);
}
} }
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj == this) try {
if (obj == this) {
return true; return true;
}
if (!(obj instanceof SecretKey)) if (!(obj instanceof SecretKey)) {
return false; return false;
}
SecretKey that = (SecretKey) obj; SecretKey that = (SecretKey) obj;
if (!(that.getAlgorithm().equalsIgnoreCase(getAlgorithm()))) if (!(that.getAlgorithm().equalsIgnoreCase(getAlgorithm()))) {
return false; return false;
if (!(that.getFormat().equalsIgnoreCase("RAW"))) }
if (!(that.getFormat().equalsIgnoreCase("RAW"))) {
return false; return false;
}
byte[] thatEncoded = that.getEncoded(); byte[] thatEncoded = that.getEncoded();
boolean ret = MessageDigest.isEqual(key, thatEncoded); boolean ret = MessageDigest.isEqual(key, thatEncoded);
Arrays.fill(thatEncoded, (byte)0x00); Arrays.fill(thatEncoded, (byte)0x00);
return ret; return ret;
} finally {
// prevent this from being cleaned for the above block
Reference.reachabilityFence(this);
}
} }
/** /**
@ -273,7 +299,12 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
*/ */
@java.io.Serial @java.io.Serial
private Object writeReplace() throws ObjectStreamException { private Object writeReplace() throws ObjectStreamException {
try {
return new KeyRep(KeyRep.Type.SECRET, getAlgorithm(), return new KeyRep(KeyRep.Type.SECRET, getAlgorithm(),
getFormat(), key); getFormat(), key);
} finally {
// prevent this from being cleaned for the above block
Reference.reachabilityFence(this);
}
} }
} }