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)) {
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) {
verifyTimestamp(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 verifyTimestamp(X509Certificate cert)
throws CertPathValidatorException
{
String msg = "timestamp";
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 " +