|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.security.provider.certpath; |
|
|
|
import java.math.BigInteger; |
|
import java.util.Collection; |
|
import java.util.Date; |
|
import java.util.Set; |
|
import java.security.GeneralSecurityException; |
|
import java.security.KeyFactory; |
|
import java.security.PublicKey; |
|
import java.security.SignatureException; |
|
import java.security.cert.Certificate; |
|
import java.security.cert.CertificateExpiredException; |
|
import java.security.cert.CertificateNotYetValidException; |
|
import java.security.cert.CertPathValidatorException; |
|
import java.security.cert.CertPathValidatorException.BasicReason; |
|
import java.security.cert.X509Certificate; |
|
import java.security.cert.PKIXCertPathChecker; |
|
import java.security.cert.PKIXReason; |
|
import java.security.cert.TrustAnchor; |
|
import java.security.interfaces.DSAParams; |
|
import java.security.interfaces.DSAPublicKey; |
|
import java.security.spec.DSAPublicKeySpec; |
|
import javax.security.auth.x500.X500Principal; |
|
import sun.security.x509.X500Name; |
|
import sun.security.util.Debug; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
class BasicChecker extends PKIXCertPathChecker { |
|
|
|
private static final Debug debug = Debug.getInstance("certpath"); |
|
private final PublicKey trustedPubKey; |
|
private final X500Principal caName; |
|
private final Date date; |
|
private final String sigProvider; |
|
private final boolean sigOnly; |
|
private X500Principal prevSubject; |
|
private PublicKey prevPubKey; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
BasicChecker(TrustAnchor anchor, Date date, String sigProvider, |
|
boolean sigOnly) { |
|
if (anchor.getTrustedCert() != null) { |
|
this.trustedPubKey = anchor.getTrustedCert().getPublicKey(); |
|
this.caName = anchor.getTrustedCert().getSubjectX500Principal(); |
|
} else { |
|
this.trustedPubKey = anchor.getCAPublicKey(); |
|
this.caName = anchor.getCA(); |
|
} |
|
this.date = date; |
|
this.sigProvider = sigProvider; |
|
this.sigOnly = sigOnly; |
|
this.prevPubKey = trustedPubKey; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public void init(boolean forward) throws CertPathValidatorException { |
|
if (!forward) { |
|
prevPubKey = trustedPubKey; |
|
if (PKIX.isDSAPublicKeyWithoutParams(prevPubKey)) { |
|
// If TrustAnchor is a DSA public key and it has no params, it |
|
// cannot be used to verify the signature of the first cert, |
|
|
|
throw new CertPathValidatorException("Key parameters missing"); |
|
} |
|
prevSubject = caName; |
|
} else { |
|
throw new |
|
CertPathValidatorException("forward checking not supported"); |
|
} |
|
} |
|
|
|
@Override |
|
public boolean isForwardCheckingSupported() { |
|
return false; |
|
} |
|
|
|
@Override |
|
public Set<String> getSupportedExtensions() { |
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public void check(Certificate cert, Collection<String> unresolvedCritExts) |
|
throws CertPathValidatorException |
|
{ |
|
X509Certificate currCert = (X509Certificate)cert; |
|
|
|
if (!sigOnly) { |
|
verifyValidity(currCert); |
|
verifyNameChaining(currCert); |
|
} |
|
verifySignature(currCert); |
|
|
|
updateState(currCert); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private void verifySignature(X509Certificate cert) |
|
throws CertPathValidatorException |
|
{ |
|
String msg = "signature"; |
|
if (debug != null) |
|
debug.println("---checking " + msg + "..."); |
|
|
|
try { |
|
cert.verify(prevPubKey, sigProvider); |
|
} catch (SignatureException e) { |
|
throw new CertPathValidatorException |
|
(msg + " check failed", e, null, -1, |
|
BasicReason.INVALID_SIGNATURE); |
|
} catch (GeneralSecurityException e) { |
|
throw new CertPathValidatorException(msg + " check failed", e); |
|
} |
|
|
|
if (debug != null) |
|
debug.println(msg + " verified."); |
|
} |
|
|
|
|
|
|
|
*/ |
|
private void verifyValidity(X509Certificate cert) |
|
throws CertPathValidatorException |
|
{ |
|
String msg = "validity"; |
|
if (debug != null) |
|
debug.println("---checking " + msg + ":" + date.toString() + "..."); |
|
|
|
try { |
|
cert.checkValidity(date); |
|
} catch (CertificateExpiredException e) { |
|
throw new CertPathValidatorException |
|
(msg + " check failed", e, null, -1, BasicReason.EXPIRED); |
|
} catch (CertificateNotYetValidException e) { |
|
throw new CertPathValidatorException |
|
(msg + " check failed", e, null, -1, BasicReason.NOT_YET_VALID); |
|
} |
|
|
|
if (debug != null) |
|
debug.println(msg + " verified."); |
|
} |
|
|
|
|
|
|
|
*/ |
|
private void verifyNameChaining(X509Certificate cert) |
|
throws CertPathValidatorException |
|
{ |
|
if (prevSubject != null) { |
|
|
|
String msg = "subject/issuer name chaining"; |
|
if (debug != null) |
|
debug.println("---checking " + msg + "..."); |
|
|
|
X500Principal currIssuer = cert.getIssuerX500Principal(); |
|
|
|
|
|
if (X500Name.asX500Name(currIssuer).isEmpty()) { |
|
throw new CertPathValidatorException |
|
(msg + " check failed: " + |
|
"empty/null issuer DN in certificate is invalid", null, |
|
null, -1, PKIXReason.NAME_CHAINING); |
|
} |
|
|
|
if (!(currIssuer.equals(prevSubject))) { |
|
throw new CertPathValidatorException |
|
(msg + " check failed", null, null, -1, |
|
PKIXReason.NAME_CHAINING); |
|
} |
|
|
|
if (debug != null) |
|
debug.println(msg + " verified."); |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
private void updateState(X509Certificate currCert) |
|
throws CertPathValidatorException |
|
{ |
|
PublicKey cKey = currCert.getPublicKey(); |
|
if (debug != null) { |
|
debug.println("BasicChecker.updateState issuer: " + |
|
currCert.getIssuerX500Principal().toString() + "; subject: " + |
|
currCert.getSubjectX500Principal() + "; serial#: " + |
|
currCert.getSerialNumber().toString()); |
|
} |
|
if (PKIX.isDSAPublicKeyWithoutParams(cKey)) { |
|
|
|
cKey = makeInheritedParamsKey(cKey, prevPubKey); |
|
if (debug != null) debug.println("BasicChecker.updateState Made " + |
|
"key with inherited params"); |
|
} |
|
prevPubKey = cKey; |
|
prevSubject = currCert.getSubjectX500Principal(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
static PublicKey makeInheritedParamsKey(PublicKey keyValueKey, |
|
PublicKey keyParamsKey) throws CertPathValidatorException |
|
{ |
|
if (!(keyValueKey instanceof DSAPublicKey) || |
|
!(keyParamsKey instanceof DSAPublicKey)) |
|
throw new CertPathValidatorException("Input key is not " + |
|
"appropriate type for " + |
|
"inheriting parameters"); |
|
DSAParams params = ((DSAPublicKey)keyParamsKey).getParams(); |
|
if (params == null) |
|
throw new CertPathValidatorException("Key parameters missing"); |
|
try { |
|
BigInteger y = ((DSAPublicKey)keyValueKey).getY(); |
|
KeyFactory kf = KeyFactory.getInstance("DSA"); |
|
DSAPublicKeySpec ks = new DSAPublicKeySpec(y, |
|
params.getP(), |
|
params.getQ(), |
|
params.getG()); |
|
return kf.generatePublic(ks); |
|
} catch (GeneralSecurityException e) { |
|
throw new CertPathValidatorException("Unable to generate key with" + |
|
" inherited parameters: " + |
|
e.getMessage(), e); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
PublicKey getPublicKey() { |
|
return prevPubKey; |
|
} |
|
} |