8175029: StackOverflowError in X509CRL and X509Certificate.verify(PublicKey, Provider)

Reviewed-by: weijun, vinnie
This commit is contained in:
Sean Mullan 2017-03-31 13:28:26 -04:00
parent 4772c1128d
commit 330b9195c9
7 changed files with 359 additions and 75 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
@ -32,6 +32,7 @@ import java.security.SignatureException;
import java.security.Principal;
import java.security.Provider;
import java.security.PublicKey;
import java.security.Signature;
import javax.security.auth.x500.X500Principal;
import java.math.BigInteger;
@ -241,7 +242,17 @@ public abstract class X509CRL extends CRL implements X509Extension {
public void verify(PublicKey key, Provider sigProvider)
throws CRLException, NoSuchAlgorithmException,
InvalidKeyException, SignatureException {
X509CRLImpl.verify(this, key, sigProvider);
Signature sig = (sigProvider == null)
? Signature.getInstance(getSigAlgName())
: Signature.getInstance(getSigAlgName(), sigProvider);
sig.initVerify(key);
byte[] tbsCRL = getTBSCertList();
sig.update(tbsCRL, 0, tbsCRL.length);
if (sig.verify(getSignature()) == false) {
throw new SignatureException("Signature does not match.");
}
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
@ -647,7 +647,7 @@ implements X509Extension {
return X509CertImpl.getIssuerAlternativeNames(this);
}
/**
/**
* Verifies that this certificate was signed using the
* private key that corresponds to the specified public key.
* This method uses the signature verification engine
@ -673,6 +673,16 @@ implements X509Extension {
public void verify(PublicKey key, Provider sigProvider)
throws CertificateException, NoSuchAlgorithmException,
InvalidKeyException, SignatureException {
X509CertImpl.verify(this, key, sigProvider);
Signature sig = (sigProvider == null)
? Signature.getInstance(getSigAlgName())
: Signature.getInstance(getSigAlgName(), sigProvider);
sig.initVerify(key);
byte[] tbsCert = getTBSCertificate();
sig.update(tbsCert, 0, tbsCert.length);
if (sig.verify(getSignature()) == false) {
throw new SignatureException("Signature does not match.");
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
@ -442,18 +442,6 @@ public class X509CRLImpl extends X509CRL implements DerEncoder {
verifiedPublicKey = key;
}
/**
* This static method is the default implementation of the
* verify(PublicKey key, Provider sigProvider) method in X509CRL.
* Called from java.security.cert.X509CRL.verify(PublicKey key,
* Provider sigProvider)
*/
public static void verify(X509CRL crl, PublicKey key,
Provider sigProvider) throws CRLException,
NoSuchAlgorithmException, InvalidKeyException, SignatureException {
crl.verify(key, sigProvider);
}
/**
* Encodes an X.509 CRL, and signs it using the given key.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2017, 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
@ -494,18 +494,6 @@ public class X509CertImpl extends X509Certificate implements DerEncoder {
}
}
/**
* This static method is the default implementation of the
* verify(PublicKey key, Provider sigProvider) method in X509Certificate.
* Called from java.security.cert.X509Certificate.verify(PublicKey key,
* Provider sigProvider)
*/
public static void verify(X509Certificate cert, PublicKey key,
Provider sigProvider) throws CertificateException,
NoSuchAlgorithmException, InvalidKeyException, SignatureException {
cert.verify(key, sigProvider);
}
/**
* Creates an X.509 certificate, and signs it using the given key
* (associating a signature algorithm and an X.500 name).

View File

@ -0,0 +1,133 @@
/*
* Copyright (c) 2017, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8175029
* @library ../../testlibrary
* @summary check that default implementation of
* X509CRL.verify(PublicKey, Provider) works on custom X509CRL impl.
*/
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Principal;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CRLException;
import java.security.cert.X509Certificate;
import java.security.cert.X509CRL;
import java.security.cert.X509CRLEntry;
import java.util.Date;
import java.util.Set;
public class VerifyDefault {
private static final String TEST_CRL =
"-----BEGIN X509 CRL-----\n" +
"MIIBGzCBhQIBATANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQMA4GA1UE\n" +
"ChMHRXhhbXBsZRcNMDkwNDI3MDIzODA0WhcNMjgwNjI2MDIzODA0WjAiMCACAQUX\n" +
"DTA5MDQyNzAyMzgwMFowDDAKBgNVHRUEAwoBBKAOMAwwCgYDVR0UBAMCAQIwDQYJ\n" +
"KoZIhvcNAQEEBQADgYEAoarfzXEtw3ZDi4f9U8eSvRIipHSyxOrJC7HR/hM5VhmY\n" +
"CErChny6x9lBVg9s57tfD/P9PSzBLusCcHwHMAbMOEcTltVVKUWZnnbumpywlYyg\n" +
"oKLrE9+yCOkYUOpiRlz43/3vkEL5hjIKMcDSZnPKBZi1h16Yj2hPe9GMibNip54=\n" +
"-----END X509 CRL-----";
private static final String TEST_CERT =
"-----BEGIN CERTIFICATE-----\n" +
"MIICKzCCAZSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ\n" +
"MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA0MjcwMjI0MzNaFw0yOTAxMTIwMjI0MzNa\n" +
"MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB\n" +
"AQUAA4GNADCBiQKBgQDMJeBMBybHykI/YpwUJ4O9euqDSLb1kpWpceBS8TVqvgBC\n" +
"SgUJWtFZL0i6bdvF6mMdlbuBkGzhXqHiVAi96/zRLbUC9F8SMEJ6MuD+YhQ0ZFTQ\n" +
"atKy8zf8O9XzztelLJ26Gqb7QPV133WY3haAqHtCXOhEKkCN16NOYNC37DTaJwID\n" +
"AQABo3cwdTAdBgNVHQ4EFgQULXSWzXzUOIpOJpzbSCpW42IJUugwRwYDVR0jBEAw\n" +
"PoAUgiXdIaZeT3QA/SGUvh854OJVyxuhI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" +
"VQQKEwdFeGFtcGxlggEAMAsGA1UdDwQEAwIBAjANBgkqhkiG9w0BAQQFAAOBgQAY\n" +
"eMnf5AHSNlyUlzXk8o2S0h4gCuvKX6C3kFfKuZcWvFAbx4yQOWLS2s15/nzR4+AP\n" +
"FGX3lgJjROyAh7fGedTQK+NFWwkM2ag1g3hXktnlnT1qHohi0w31nVBJxXEDO/Ck\n" +
"uJTpJGt8XxxbFaw5v7cHy7XuTAeU/sekvjEiNHW00Q==\n" +
"-----END CERTIFICATE-----";
private static class TestX509CRL extends X509CRL {
private final X509CRL crl;
TestX509CRL(X509CRL crl) {
this.crl = crl;
}
public Set<String> getCriticalExtensionOIDs() {
return crl.getCriticalExtensionOIDs();
}
public byte[] getExtensionValue(String oid) {
return crl.getExtensionValue(oid);
}
public Set<String> getNonCriticalExtensionOIDs() {
return crl.getNonCriticalExtensionOIDs();
}
public boolean hasUnsupportedCriticalExtension() {
return crl.hasUnsupportedCriticalExtension();
}
public Set<? extends X509CRLEntry> getRevokedCertificates() {
return crl.getRevokedCertificates();
}
public X509CRLEntry getRevokedCertificate(BigInteger serialNumber) {
return crl.getRevokedCertificate(serialNumber);
}
public boolean isRevoked(Certificate cert) {
return crl.isRevoked(cert);
}
public Date getNextUpdate() { return crl.getNextUpdate(); }
public Date getThisUpdate() { return crl.getThisUpdate(); }
public int getVersion() { return crl.getVersion(); }
public Principal getIssuerDN() { return crl.getIssuerDN(); }
public byte[] getTBSCertList() throws CRLException {
return crl.getTBSCertList();
}
public byte[] getSignature() { return crl.getSignature(); }
public String getSigAlgName() { return crl.getSigAlgName(); }
public String getSigAlgOID() { return crl.getSigAlgOID(); }
public byte[] getSigAlgParams() { return crl.getSigAlgParams(); }
public byte[] getEncoded() throws CRLException {
return crl.getEncoded();
}
public void verify(PublicKey key) throws CRLException,
InvalidKeyException, NoSuchAlgorithmException,
NoSuchProviderException, SignatureException {
crl.verify(key);
}
public void verify(PublicKey key, String sigProvider) throws
CRLException, InvalidKeyException, NoSuchAlgorithmException,
NoSuchProviderException, SignatureException {
crl.verify(key, sigProvider);
}
public String toString() { return crl.toString(); }
}
public static void main(String[] args) throws Exception {
X509Certificate cert = CertUtils.getCertFromString(TEST_CERT);
X509CRL crl = CertUtils.getCRLFromString(TEST_CRL);
new TestX509CRL(crl).verify(cert.getPublicKey(), (Provider)null);
}
}

View File

@ -0,0 +1,139 @@
/*
* Copyright (c) 2017, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8175029
* @library ../../testlibrary
* @summary check that default implementation of
* X509Certificate.verify(PublicKey, Provider) works on custom
* X509Certificate impl.
*/
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Principal;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Set;
public class VerifyDefault {
private static final String TEST_CERT =
"-----BEGIN CERTIFICATE-----\n" +
"MIICvTCCAaWgAwIBAgIEGYqL9TANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRT\n" +
"ZWxmMB4XDTE3MDMyODE2NDcyNloXDTE3MDYyNjE2NDcyNlowDzENMAsGA1UEAxME\n" +
"U2VsZjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL1pfSJljFVSABOL\n" +
"tJbIVPEkz1+2AFgzY1hqwE0EH80lvhOEkiPPYCKwBE5VTZdyFfwFjpyx7eEeJMNT\n" +
"o7cixfmkQaiXHr/S1AS4BRTqLG/zgLzoJpVbzi45rnVEZc0oTm11KG3uUxkZTRr3\n" +
"5ORbYyZpkscKwHL2M0J/1GmnA1hmhQdwUQyIKxg4eKQwyE+/TdbFlCWVNnOlb+91\n" +
"eXvS11nIJ1oaBgn7u4qihuVmFmngLMxExnLYKV6AwdkwFD6pERObclRD9vAl5eUk\n" +
"+sM6zQYwfLdyC2i8e+ETBeOg1ijptM4KT5Uaq89zxjLR0DPH4S+aILp3gYHGrW5r\n" +
"eMxZAEMCAwEAAaMhMB8wHQYDVR0OBBYEFOME39JtbjzQaK3ufpKo/Pl4sZ8XMA0G\n" +
"CSqGSIb3DQEBCwUAA4IBAQCDcw0+Sf0yeVROVlb2/VV3oIblHkGQheXeIurW64k7\n" +
"tEzHtx9i8dnj5lzTZNH6hU4GRlyULbSDzjcM3P2XFRsM+0a/kEJZVqnLz5ji//7/\n" +
"ZXaRX0TiE2IfFOTGbO6LusO3yR4tOER/WHllz2H21C2SbW3+92Ou28glTZa42AAZ\n" +
"mUj9j+p6mZqD4/tUBqAEqqQoMIhw9CNjc46STNayBjt/0/+I2pfy6LagrMbjBzZ0\n" +
"A5kXg9WjnywGk8XFr/3RZz8DrUmCYs2qCYLCHQHsuCE6gCuf9wKhKyD51MFXXRr0\n" +
"cyG6LYQjrreMHYk4ZfN2NPC6lGjWxB5mIbV/DuikCnYu\n" +
"-----END CERTIFICATE-----";
private static class TestX509Certificate extends X509Certificate {
private final X509Certificate cert;
TestX509Certificate(X509Certificate cert) {
this.cert = cert;
}
public Set<String> getCriticalExtensionOIDs() {
return cert.getCriticalExtensionOIDs();
}
public byte[] getExtensionValue(String oid) {
return cert.getExtensionValue(oid);
}
public Set<String> getNonCriticalExtensionOIDs() {
return cert.getNonCriticalExtensionOIDs();
}
public boolean hasUnsupportedCriticalExtension() {
return cert.hasUnsupportedCriticalExtension();
}
public void checkValidity() throws CertificateExpiredException,
CertificateNotYetValidException {
cert.checkValidity();
}
public void checkValidity(Date date) throws CertificateExpiredException,
CertificateNotYetValidException {
cert.checkValidity(date);
}
public int getVersion() { return cert.getVersion(); }
public BigInteger getSerialNumber() { return cert.getSerialNumber(); }
public Principal getIssuerDN() { return cert.getIssuerDN(); }
public Principal getSubjectDN() { return cert.getSubjectDN(); }
public Date getNotBefore() { return cert.getNotBefore(); }
public Date getNotAfter() { return cert.getNotAfter(); }
public byte[] getTBSCertificate() throws CertificateEncodingException {
return cert.getTBSCertificate();
}
public byte[] getSignature() { return cert.getSignature(); }
public String getSigAlgName() { return cert.getSigAlgName(); }
public String getSigAlgOID() { return cert.getSigAlgOID(); }
public byte[] getSigAlgParams() { return cert.getSigAlgParams(); }
public boolean[] getIssuerUniqueID() {
return cert.getIssuerUniqueID();
}
public boolean[] getSubjectUniqueID() {
return cert.getSubjectUniqueID();
}
public boolean[] getKeyUsage() { return cert.getKeyUsage(); }
public int getBasicConstraints() { return cert.getBasicConstraints(); }
public byte[] getEncoded() throws CertificateEncodingException {
return cert.getEncoded();
}
public void verify(PublicKey key) throws CertificateException,
InvalidKeyException, NoSuchAlgorithmException,
NoSuchProviderException, SignatureException {
cert.verify(key);
}
public void verify(PublicKey key, String sigProvider) throws
CertificateException, InvalidKeyException, NoSuchAlgorithmException,
NoSuchProviderException, SignatureException {
cert.verify(key, sigProvider);
}
public PublicKey getPublicKey() { return cert.getPublicKey(); }
public String toString() { return cert.toString(); }
}
public static void main(String[] args) throws Exception {
X509Certificate cert = CertUtils.getCertFromString(TEST_CERT);
new TestX509Certificate(cert).verify(cert.getPublicKey(),
(Provider)null);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2017, 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
@ -27,17 +27,20 @@
* @author Steve Hanna
*
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertPath;
import java.security.cert.CertPathBuilder;
import java.security.cert.CertPathValidator;
import java.security.cert.CertStore;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.CRLException;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.PKIXCertPathBuilderResult;
import java.security.cert.PKIXCertPathValidatorResult;
@ -60,59 +63,71 @@ public class CertUtils {
* Get a DER-encoded X.509 certificate from a file.
*
* @param certFilePath path to file containing DER-encoded certificate
* @return X509Certificate
* @throws IOException on error
* @return the X509Certificate
* @throws CertificateException if the certificate type is not supported
* or cannot be parsed
* @throws IOException if the file cannot be opened
*/
public static X509Certificate getCertFromFile(String certFilePath)
throws IOException {
X509Certificate cert = null;
try {
File certFile = new File(System.getProperty("test.src", "."),
certFilePath);
if (!certFile.canRead())
throw new IOException("File " +
certFile.toString() +
" is not a readable file.");
FileInputStream certFileInputStream =
new FileInputStream(certFile);
CertificateFactory cf = CertificateFactory.getInstance("X509");
cert = (X509Certificate)
cf.generateCertificate(certFileInputStream);
} catch (Exception e) {
e.printStackTrace();
throw new IOException("Can't construct X509Certificate: " +
e.getMessage());
}
return cert;
throws CertificateException, IOException {
File certFile = new File(System.getProperty("test.src", "."),
certFilePath);
try (FileInputStream fis = new FileInputStream(certFile)) {
return (X509Certificate)
CertificateFactory.getInstance("X.509")
.generateCertificate(fis);
}
}
/**
* Get a PEM-encoded X.509 certificate from a string.
*
* @param cert string containing the PEM-encoded certificate
* @return the X509Certificate
* @throws CertificateException if the certificate type is not supported
* or cannot be parsed
*/
public static X509Certificate getCertFromString(String cert)
throws CertificateException {
byte[] certBytes = cert.getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(certBytes);
return (X509Certificate)
CertificateFactory.getInstance("X.509").generateCertificate(bais);
}
/**
* Get a DER-encoded X.509 CRL from a file.
*
* @param crlFilePath path to file containing DER-encoded CRL
* @return X509CRL
* @throws IOException on error
* @return the X509CRL
* @throws CertificateException if the crl type is not supported
* @throws CRLException if the crl cannot be parsed
* @throws IOException if the file cannot be opened
*/
public static X509CRL getCRLFromFile(String crlFilePath)
throws IOException {
X509CRL crl = null;
try {
File crlFile = new File(System.getProperty("test.src", "."),
crlFilePath);
if (!crlFile.canRead())
throw new IOException("File " +
crlFile.toString() +
" is not a readable file.");
FileInputStream crlFileInputStream =
new FileInputStream(crlFile);
CertificateFactory cf = CertificateFactory.getInstance("X509");
crl = (X509CRL) cf.generateCRL(crlFileInputStream);
} catch (Exception e) {
e.printStackTrace();
throw new IOException("Can't construct X509CRL: " +
e.getMessage());
}
return crl;
throws CertificateException, CRLException, IOException {
File crlFile = new File(System.getProperty("test.src", "."),
crlFilePath);
try (FileInputStream fis = new FileInputStream(crlFile)) {
return (X509CRL)
CertificateFactory.getInstance("X.509").generateCRL(fis);
}
}
/**
* Get a PEM-encoded X.509 crl from a string.
*
* @param crl string containing the PEM-encoded crl
* @return the X509CRL
* @throws CertificateException if the crl type is not supported
* @throws CRLException if the crl cannot be parsed
*/
public static X509CRL getCRLFromString(String crl)
throws CertificateException, CRLException {
byte[] crlBytes = crl.getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(crlBytes);
return (X509CRL)
CertificateFactory.getInstance("X.509").generateCRL(bais);
}
/**