Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cloneable test in HmacCore seems questionable #667

Merged
merged 1 commit into from
Jun 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ abstract class HmacCore extends MacSpi implements Cloneable {
} else {
String noCloneProv = md.getProvider().getName();
// if no Sun provider, use provider list
md = null;
Provider[] provs = Security.getProviders();
for (Provider p : provs) {
try {
Expand All @@ -82,6 +83,10 @@ abstract class HmacCore extends MacSpi implements Cloneable {
continue;
}
}
if (md == null) {
throw new NoSuchAlgorithmException
("No Cloneable digest found for " + digestAlgo);
}
}
}
this.md = md;
Expand Down
84 changes: 64 additions & 20 deletions src/java.base/share/classes/java/security/MessageDigest.java
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ protected MessageDigest(String algorithm) {
this.algorithm = algorithm;
}

// private constructor used only by Delegate class
private MessageDigest(String algorithm, Provider p) {
this.algorithm = algorithm;
this.provider = p;
}

/**
* Returns a MessageDigest object that implements the specified digest
* algorithm.
Expand Down Expand Up @@ -179,10 +185,11 @@ public static MessageDigest getInstance(String algorithm)
(String)null);
if (objs[0] instanceof MessageDigest) {
md = (MessageDigest)objs[0];
md.provider = (Provider)objs[1];
} else {
md = new Delegate((MessageDigestSpi)objs[0], algorithm);
md = Delegate.of((MessageDigestSpi)objs[0], algorithm,
(Provider) objs[1]);
}
md.provider = (Provider)objs[1];

if (!skipDebug && pdebug != null) {
pdebug.println("MessageDigest." + algorithm +
Expand Down Expand Up @@ -246,8 +253,8 @@ public static MessageDigest getInstance(String algorithm, String provider)
return md;
} else {
MessageDigest delegate =
new Delegate((MessageDigestSpi)objs[0], algorithm);
delegate.provider = (Provider)objs[1];
Delegate.of((MessageDigestSpi)objs[0], algorithm,
(Provider)objs[1]);
return delegate;
}
}
Expand Down Expand Up @@ -299,8 +306,8 @@ public static MessageDigest getInstance(String algorithm,
return md;
} else {
MessageDigest delegate =
new Delegate((MessageDigestSpi)objs[0], algorithm);
delegate.provider = (Provider)objs[1];
Delegate.of((MessageDigestSpi)objs[0], algorithm,
(Provider)objs[1]);
return delegate;
}
}
Expand Down Expand Up @@ -558,8 +565,6 @@ public Object clone() throws CloneNotSupportedException {
}




/*
* The following class allows providers to extend from MessageDigestSpi
* rather than from MessageDigest. It represents a MessageDigest with an
Expand All @@ -574,14 +579,45 @@ public Object clone() throws CloneNotSupportedException {
* and its original parent (Object).
*/

static class Delegate extends MessageDigest implements MessageDigestSpi2 {
private static class Delegate extends MessageDigest
implements MessageDigestSpi2 {
// use this class for spi objects which implements Cloneable
private static final class CloneableDelegate extends Delegate
implements Cloneable {

private CloneableDelegate(MessageDigestSpi digestSpi,
String algorithm, Provider p) {
super(digestSpi, algorithm, p);
}
}

// The provider implementation (delegate)
private MessageDigestSpi digestSpi;
private final MessageDigestSpi digestSpi;

// factory method used by MessageDigest class to create Delegate objs
static Delegate of(MessageDigestSpi digestSpi, String algo,
Provider p) {
Objects.requireNonNull(digestSpi);
boolean isCloneable = (digestSpi instanceof Cloneable);
// Spi impls from SunPKCS11 provider implement Cloneable but their
// clone() may throw CloneNotSupportException
if (isCloneable && p.getName().startsWith("SunPKCS11") &&
p.getClass().getModule().getName().equals
("jdk.crypto.cryptoki")) {
try {
digestSpi.clone();
} catch (CloneNotSupportedException cnse) {
isCloneable = false;
}
}
return (isCloneable? new CloneableDelegate(digestSpi, algo, p) :
new Delegate(digestSpi, algo, p));
}

// constructor
public Delegate(MessageDigestSpi digestSpi, String algorithm) {
super(algorithm);
// private constructor
private Delegate(MessageDigestSpi digestSpi, String algorithm,
Provider p) {
super(algorithm, p);
this.digestSpi = digestSpi;
}

Expand All @@ -593,40 +629,44 @@ public Delegate(MessageDigestSpi digestSpi, String algorithm) {
* @exception CloneNotSupportedException if this is called on a
* delegate that does not support {@code Cloneable}.
*/
@Override
public Object clone() throws CloneNotSupportedException {
if (digestSpi instanceof Cloneable) {
MessageDigestSpi digestSpiClone =
(MessageDigestSpi)digestSpi.clone();
if (this instanceof Cloneable) {
// Because 'algorithm', 'provider', and 'state' are private
// members of our supertype, we must perform a cast to
// access them.
MessageDigest that =
new Delegate(digestSpiClone,
((MessageDigest)this).algorithm);
that.provider = ((MessageDigest)this).provider;
MessageDigest that = new CloneableDelegate(
(MessageDigestSpi)digestSpi.clone(),
((MessageDigest)this).algorithm,
((MessageDigest)this).provider);
that.state = ((MessageDigest)this).state;
return that;
} else {
throw new CloneNotSupportedException();
}
}

@Override
protected int engineGetDigestLength() {
return digestSpi.engineGetDigestLength();
}

@Override
protected void engineUpdate(byte input) {
digestSpi.engineUpdate(input);
}

@Override
protected void engineUpdate(byte[] input, int offset, int len) {
digestSpi.engineUpdate(input, offset, len);
}

@Override
protected void engineUpdate(ByteBuffer input) {
digestSpi.engineUpdate(input);
}

@Override
public void engineUpdate(SecretKey key) throws InvalidKeyException {
if (digestSpi instanceof MessageDigestSpi2) {
((MessageDigestSpi2)digestSpi).engineUpdate(key);
Expand All @@ -635,15 +675,19 @@ public void engineUpdate(SecretKey key) throws InvalidKeyException {
("Digest does not support update of SecretKey object");
}
}

@Override
protected byte[] engineDigest() {
return digestSpi.engineDigest();
}

@Override
protected int engineDigest(byte[] buf, int offset, int len)
throws DigestException {
return digestSpi.engineDigest(buf, offset, len);
}

@Override
protected void engineReset() {
digestSpi.engineReset();
}
Expand Down
38 changes: 28 additions & 10 deletions src/java.base/share/classes/java/security/Signature.java
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ public static Signature getInstance(String algorithm)
NoSuchAlgorithmException failure;
do {
Service s = t.next();
if (isSpi(s)) {
if (isSpi(s)) { // delayed provider selection
return new Delegate(s, t, algorithm);
} else {
// must be a subclass of Signature, disable dynamic selection
Expand All @@ -294,7 +294,7 @@ private static Signature getInstance(Instance instance, String algorithm) {
sig.algorithm = algorithm;
} else {
SignatureSpi spi = (SignatureSpi)instance.impl;
sig = new Delegate(spi, algorithm);
sig = Delegate.of(spi, algorithm);
}
sig.provider = instance.provider;
return sig;
Expand Down Expand Up @@ -464,7 +464,7 @@ private static Signature getInstanceRSA(Provider p)
// check Cipher
try {
Cipher c = Cipher.getInstance(RSA_CIPHER, p);
return new Delegate(new CipherAdapter(c), RSA_SIGNATURE);
return Delegate.of(new CipherAdapter(c), RSA_SIGNATURE);
} catch (GeneralSecurityException e) {
// throw Signature style exception message to avoid confusion,
// but append Cipher exception as cause
Expand Down Expand Up @@ -1090,6 +1090,14 @@ public Object clone() throws CloneNotSupportedException {

@SuppressWarnings("deprecation")
private static class Delegate extends Signature {
// use this class for spi objects which implements Cloneable
private static final class CloneableDelegate extends Delegate
implements Cloneable {
private CloneableDelegate(SignatureSpi digestSpi,
String algorithm) {
super(digestSpi, algorithm);
}
}

// The provider implementation (delegate)
// filled in once the provider is selected
Expand All @@ -1106,15 +1114,24 @@ private static class Delegate extends Signature {
// null once provider is selected
private Iterator<Service> serviceIterator;

// constructor
Delegate(SignatureSpi sigSpi, String algorithm) {
// factory method used by Signature class to create Delegate objs
static Delegate of(SignatureSpi sigSpi, String algorithm) {
if (sigSpi instanceof Cloneable) {
return new CloneableDelegate(sigSpi, algorithm);
} else {
return new Delegate(sigSpi, algorithm);
}
}

// private constructor
private Delegate(SignatureSpi sigSpi, String algorithm) {
super(algorithm);
this.sigSpi = sigSpi;
this.lock = null; // no lock needed
}

// used with delayed provider selection
Delegate(Service service,
// constructor used with delayed provider selection
private Delegate(Service service,
Iterator<Service> iterator, String algorithm) {
super(algorithm);
this.firstService = service;
Expand All @@ -1130,15 +1147,16 @@ private static class Delegate extends Signature {
* @exception CloneNotSupportedException if this is called on a
* delegate that does not support {@code Cloneable}.
*/
@Override
public Object clone() throws CloneNotSupportedException {
chooseFirstProvider();
if (sigSpi instanceof Cloneable) {
SignatureSpi sigSpiClone = (SignatureSpi)sigSpi.clone();
// Because 'algorithm' and 'provider' are private
// members of our supertype, we must perform a cast to
// access them.
Signature that =
new Delegate(sigSpiClone, ((Signature)this).algorithm);
Signature that = new CloneableDelegate(
(SignatureSpi)sigSpi.clone(),
((Signature)this).algorithm);
that.provider = ((Signature)this).provider;
return that;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ protected final int engineDigest(byte[] out, int ofs, int len)
public Object clone() throws CloneNotSupportedException {
DigestBase copy = (DigestBase) super.clone();
copy.buffer = copy.buffer.clone();
copy.oneByte = null;
return copy;
}

Expand Down
Loading