Skip to content

Commit

Permalink
Cloneable test in HmacCore seems questionable
Browse files Browse the repository at this point in the history
Signed-off-by: Jinhang Zhang <Jinhang.Zhang@ibm.com>
  • Loading branch information
WilburZjh committed Jun 8, 2023
1 parent fd547bb commit b0e5257
Show file tree
Hide file tree
Showing 7 changed files with 378 additions and 33 deletions.
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
86 changes: 65 additions & 21 deletions src/java.base/share/classes/java/security/MessageDigest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2020, 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
Expand Down 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
40 changes: 29 additions & 11 deletions src/java.base/share/classes/java/security/Signature.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2018, 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
Expand Down 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
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2014, 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
Expand Down 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

0 comments on commit b0e5257

Please sign in to comment.