diff --git a/src/main/java/com/ibm/crypto/plus/provider/ECDSASignature.java b/src/main/java/com/ibm/crypto/plus/provider/ECDSASignature.java index f80c904d..5270392f 100644 --- a/src/main/java/com/ibm/crypto/plus/provider/ECDSASignature.java +++ b/src/main/java/com/ibm/crypto/plus/provider/ECDSASignature.java @@ -10,19 +10,24 @@ import com.ibm.crypto.plus.provider.ock.Signature; import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.InvalidParameterException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SignatureException; import java.security.SignatureSpi; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.ECParameterSpec; +import sun.security.util.ECUtil; import sun.security.util.ObjectIdentifier; - abstract class ECDSASignature extends SignatureSpi { private OpenJCEPlusProvider provider = null; private Signature signature = null; + private ECPrivateKey privateKey = null; + private ECPublicKey publicKey = null; ECDSASignature(OpenJCEPlusProvider provider, String ockDigestAlgo) { try { @@ -35,10 +40,10 @@ abstract class ECDSASignature extends SignatureSpi { @Override protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException { - ECPublicKey ecPublic = (ECPublicKey) ECKeyFactory.toECKey(provider, publicKey); + this.publicKey = (ECPublicKey) ECKeyFactory.toECKey(provider, publicKey); try { - this.signature.initialize(ecPublic.getOCKKey(), false); + this.signature.initialize(this.publicKey.getOCKKey(), false); } catch (Exception e) { throw provider.providerException("Failure in engineInitVerify", e); } @@ -46,12 +51,12 @@ protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException @Override protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException { - ECPrivateKey ecPrivate = (ECPrivateKey) ECKeyFactory.toECKey(provider, privateKey); - ECUtils.checkPrivateKey(ecPrivate); + this.privateKey = (ECPrivateKey) ECKeyFactory.toECKey(provider, privateKey); + ECUtils.checkPrivateKey(this.privateKey); if (this.provider.isFIPS()) { ECNamedCurve ecNamedCurve = ECParameters - .getNamedCurve(ecPrivate.getParams()); + .getNamedCurve(this.privateKey.getParams()); ObjectIdentifier oid = null; oid = ECNamedCurve.getOIDFromName(ecNamedCurve.getName()); @@ -64,7 +69,7 @@ protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException } try { - this.signature.initialize(ecPrivate.getOCKKey(), false); + this.signature.initialize(this.privateKey.getOCKKey(), false); } catch (Exception e) { throw provider.providerException("Failure in engineInitSign", e); } @@ -109,13 +114,37 @@ protected boolean engineVerify(byte[] sigBytes) throws SignatureException { } @Deprecated - protected void engineSetParameter(String param, Object value) throws InvalidParameterException { - throw new InvalidParameterException("No parameter accepted"); + @Override + protected void engineSetParameter(String param, Object value) + throws InvalidParameterException { + throw new UnsupportedOperationException("setParameter() not supported"); + } + + @Override + protected void engineSetParameter(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException { + // Interop: some certificates include parameters in an ECDSA + // algorithm identifier. We only accept one matching the key. + if (params == null) { + return; + } + if (params instanceof ECParameterSpec) { + ECParameterSpec ecparams = (ECParameterSpec) params; + java.security.interfaces.ECKey key = (this.privateKey == null? this.publicKey : this.privateKey); + if ((key != null) && !ECUtil.equals(ecparams, key.getParams())) { + throw new InvalidAlgorithmParameterException( + "Signature params does not match key params"); + } + } else { + throw new InvalidAlgorithmParameterException( + "Parameters must be of type ECParameterSpec"); + } } @Deprecated + @Override protected Object engineGetParameter(String param) throws InvalidParameterException { - return null; + throw new UnsupportedOperationException("getParameter(String param) not supported"); } @Override diff --git a/src/test/java/ibm/jceplus/junit/base/BaseTestECDSASignature.java b/src/test/java/ibm/jceplus/junit/base/BaseTestECDSASignature.java index d35f224d..a99107ca 100644 --- a/src/test/java/ibm/jceplus/junit/base/BaseTestECDSASignature.java +++ b/src/test/java/ibm/jceplus/junit/base/BaseTestECDSASignature.java @@ -11,6 +11,7 @@ import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.InvalidParameterException; import java.security.KeyFactory; @@ -18,12 +19,16 @@ import java.security.KeyPairGenerator; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.interfaces.ECPrivateKey; import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; import java.security.spec.ECPrivateKeySpec; +import java.security.spec.MGF1ParameterSpec; +import java.security.spec.PSSParameterSpec; import java.util.Arrays; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -35,6 +40,80 @@ public class BaseTestECDSASignature extends BaseTestJunit5Signature { static final byte[] origMsg = "this is the original message to be signed".getBytes(); + @Test + public void testEngineSetParameter_invalidSpec() throws Exception { + KeyPair keyPair = generateKeyPair(256); + + String sigAlgo = "SHA256withECDSA"; + PrivateKey privateKey = keyPair.getPrivate(); + PublicKey publicKey = keyPair.getPublic(); + + AlgorithmParameters pssParams = AlgorithmParameters.getInstance("RSASSA-PSS", getProviderName()); + pssParams.init(new PSSParameterSpec("SHA-1", "MGF1", MGF1ParameterSpec.SHA1, 20, 1)); + PSSParameterSpec pssParameterSpec = pssParams.getParameterSpec(PSSParameterSpec.class); + + AlgorithmParameters ecParams = AlgorithmParameters.getInstance("EC", getProviderName()); + ecParams.init(new ECGenParameterSpec("secp521r1")); + ECParameterSpec ecParameterSpec = ecParams.getParameterSpec(ECParameterSpec.class); + + Signature signing = Signature.getInstance(sigAlgo, getProviderName()); + signing.initSign(privateKey); + + // Check with different type of AlgorithmParameterSpec. + try { + signing.setParameter(pssParameterSpec); + } catch (InvalidAlgorithmParameterException iape) { + if (!"Parameters must be of type ECParameterSpec".equals(iape.getMessage())) { + throw iape; + } + } + + // Check against private key with same type of AlgorithmParameterSpec, but different curve. + try { + signing.setParameter(ecParameterSpec); + fail("InvalidAlgorithmParameterException expected."); + } catch (InvalidAlgorithmParameterException iape) { + if (!"Signature params does not match key params".equals(iape.getMessage())) { + throw iape; + } + } + + Signature verifying = Signature.getInstance(sigAlgo, getProviderName()); + verifying.initVerify(publicKey); + + // Check against public key with same type of AlgorithmParameterSpec, but different curve. + try { + verifying.setParameter(ecParameterSpec); + fail("InvalidAlgorithmParameterException expected."); + } catch (InvalidAlgorithmParameterException iape) { + if (!"Signature params does not match key params".equals(iape.getMessage())) { + throw iape; + } + } + } + + @Test + public void testEngineSetParameter_validSpec() throws Exception { + KeyPair keyPair = generateKeyPair(256); + + String sigAlgo = "SHA256withECDSA"; + PrivateKey privateKey = keyPair.getPrivate(); + PublicKey publicKey = keyPair.getPublic(); + AlgorithmParameters params = AlgorithmParameters.getInstance("EC", getProviderName()); + params.init(new ECGenParameterSpec("secp256r1")); + ECParameterSpec ecParameters = params.getParameterSpec(ECParameterSpec.class); + + Signature signing = Signature.getInstance(sigAlgo, getProviderName()); + signing.initSign(privateKey); + // Check against private key with correct AlgorithmParameterSpec. + signing.setParameter(ecParameters); + + Signature verifying = Signature.getInstance(sigAlgo, getProviderName()); + verifying.initVerify(publicKey); + // Check against public key with correct AlgorithmParameterSpec. + verifying.setParameter(ecParameters); + } + @Test public void testSHA1withECDSA_192() throws Exception { if (getProviderName().equals("OpenJCEPlusFIPS")) {