TrustAnchor trust = null;
X500Principal trustPrincipal = null;
// validation date
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.certPathValidDate",
new Object[] {new TrustedInput(validDate), new TrustedInput(new Date())});
addNotification(msg);
}
// find trust anchors
try
{
X509Certificate cert = (X509Certificate) certs.get(certs.size() - 1);
Collection trustColl = getTrustAnchors(cert,pkixParams.getTrustAnchors());
if (trustColl.size() > 1)
{
// conflicting trust anchors
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
"CertPathReviewer.conflictingTrustAnchors",
new Object[] {new Integer(trustColl.size()),
new UntrustedInput(cert.getIssuerX500Principal())});
addError(msg);
}
else if (trustColl.isEmpty())
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,
"CertPathReviewer.noTrustAnchorFound",
new Object[] {new UntrustedInput(cert.getIssuerX500Principal()),
new Integer(pkixParams.getTrustAnchors().size())});
addError(msg);
}
else
{
PublicKey trustPublicKey;
trust = (TrustAnchor) trustColl.iterator().next();
if (trust.getTrustedCert() != null)
{
trustPublicKey = trust.getTrustedCert().getPublicKey();
}
else
{
trustPublicKey = trust.getCAPublicKey();
}
try
{
CertPathValidatorUtilities.verifyX509Certificate(cert, trustPublicKey,
pkixParams.getSigProvider());
}
catch (SignatureException e)
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.trustButInvalidCert");
addError(msg);
}
catch (Exception e)
{
// do nothing, error occurs again later
}
}
}
catch (CertPathReviewerException cpre)
{
addError(cpre.getErrorMessage());
}
if (trust != null)
{
// get the name of the trustAnchor
X509Certificate sign = trust.getTrustedCert();
try
{
if (sign != null)
{
trustPrincipal = getSubjectPrincipal(sign);
}
else
{
trustPrincipal = new X500Principal(trust.getCAName());
}
}
catch (IllegalArgumentException ex)
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.trustDNInvalid",
new Object[] {new UntrustedInput(trust.getCAName())});
addError(msg);
}
// test key usages of the trust anchor
if (sign != null)
{
boolean[] ku = sign.getKeyUsage();
if (ku != null && !ku[5])
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME, "CertPathReviewer.trustKeyUsage");
addNotification(msg);
}
}
}
// 1.6.2 - Initialization
PublicKey workingPublicKey = null;
X500Principal workingIssuerName = trustPrincipal;
X509Certificate sign = null;
AlgorithmIdentifier workingAlgId = null;
DERObjectIdentifier workingPublicKeyAlgorithm = null;
DEREncodable workingPublicKeyParameters = null;
if (trust != null)
{
sign = trust.getTrustedCert();
if (sign != null)
{
workingPublicKey = sign.getPublicKey();
}
else
{
workingPublicKey = trust.getCAPublicKey();
}
try
{
workingAlgId = getAlgorithmIdentifier(workingPublicKey);
workingPublicKeyAlgorithm = workingAlgId.getObjectId();
workingPublicKeyParameters = workingAlgId.getParameters();
}
catch (CertPathValidatorException ex)
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.trustPubKeyError");
addError(msg);
workingAlgId = null;
}
}
// Basic cert checks
X509Certificate cert = null;
int i;
for (int index = certs.size() - 1; index >= 0; index--)
{
//
// i as defined in the algorithm description
//
i = n - index;
//
// set certificate to be checked in this round
// sign and workingPublicKey and workingIssuerName are set
// at the end of the for loop and initialied the
// first time from the TrustAnchor
//
cert = (X509Certificate) certs.get(index);
// verify signature
if (workingPublicKey != null)
{
try
{
CertPathValidatorUtilities.verifyX509Certificate(cert, workingPublicKey,
pkixParams.getSigProvider());
}
catch (GeneralSecurityException ex)
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.signatureNotVerified",
new Object[] {ex.getMessage(),ex,ex.getClass().getName()});
addError(msg,index);
}
}
else if (isSelfIssued(cert))
{
try
{
CertPathValidatorUtilities.verifyX509Certificate(cert, cert.getPublicKey(),
pkixParams.getSigProvider());
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.rootKeyIsValidButNotATrustAnchor");
addError(msg, index);
}
catch (GeneralSecurityException ex)
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.signatureNotVerified",
new Object[] {ex.getMessage(),ex,ex.getClass().getName()});
addError(msg,index);
}
}
else
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.NoIssuerPublicKey");
// if there is an authority key extension add the serial and issuer of the missing certificate
byte[] akiBytes = cert.getExtensionValue(X509Extensions.AuthorityKeyIdentifier.getId());
if (akiBytes != null)
{
try
{
AuthorityKeyIdentifier aki = AuthorityKeyIdentifier.getInstance(
X509ExtensionUtil.fromExtensionValue(akiBytes));
GeneralNames issuerNames = aki.getAuthorityCertIssuer();
if (issuerNames != null)
{
GeneralName name = issuerNames.getNames()[0];
BigInteger serial = aki.getAuthorityCertSerialNumber();
if (serial != null)
{
Object[] extraArgs = {new LocaleString(RESOURCE_NAME, "missingIssuer"), " \"", name ,
"\" ", new LocaleString(RESOURCE_NAME, "missingSerial") , " ", serial};
msg.setExtraArguments(extraArgs);
}
}
}
catch (IOException e)
{
// ignore
}
}
addError(msg,index);
}
// certificate valid?
try
{
cert.checkValidity(validDate);
}
catch (CertificateNotYetValidException cnve)
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.certificateNotYetValid",
new Object[] {new TrustedInput(cert.getNotBefore())});
addError(msg,index);
}
catch (CertificateExpiredException cee)
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.certificateExpired",
new Object[] {new TrustedInput(cert.getNotAfter())});
addError(msg,index);
}
// certificate revoked?
if (pkixParams.isRevocationEnabled())
{
// read crl distribution points extension
CRLDistPoint crlDistPoints = null;
try
{
DERObject crl_dp = getExtensionValue(cert,CRL_DIST_POINTS);
if (crl_dp != null)
{
crlDistPoints = CRLDistPoint.getInstance(crl_dp);
}
}
catch (AnnotatedException ae)
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.crlDistPtExtError");
addError(msg,index);
}
// read authority information access extension
AuthorityInformationAccess authInfoAcc = null;
try
{
DERObject auth_info_acc = getExtensionValue(cert,AUTH_INFO_ACCESS);
if (auth_info_acc != null)
{
authInfoAcc = AuthorityInformationAccess.getInstance(auth_info_acc);
}
}
catch (AnnotatedException ae)
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.crlAuthInfoAccError");
addError(msg,index);
}
Vector crlDistPointUrls = getCRLDistUrls(crlDistPoints);
Vector ocspUrls = getOCSPUrls(authInfoAcc);
// add notifications with the crl distribution points
// output crl distribution points
Iterator urlIt = crlDistPointUrls.iterator();
while (urlIt.hasNext())
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.crlDistPoint",
new Object[] {new UntrustedUrlInput(urlIt.next())});
addNotification(msg,index);
}
// output ocsp urls
urlIt = ocspUrls.iterator();
while (urlIt.hasNext())
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.ocspLocation",
new Object[] {new UntrustedUrlInput(urlIt.next())});
addNotification(msg,index);
}
// TODO also support Netscapes revocation-url and/or OCSP instead of CRLs for revocation checking
// check CRLs
try
{
checkRevocation(pkixParams, cert, validDate, sign, workingPublicKey, crlDistPointUrls, ocspUrls, index);
}
catch (CertPathReviewerException cpre)
{
addError(cpre.getErrorMessage(),index);
}
}
// certificate issuer correct
if (workingIssuerName != null && !cert.getIssuerX500Principal().equals(workingIssuerName))
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.certWrongIssuer",
new Object[] {workingIssuerName.getName(),
cert.getIssuerX500Principal().getName()});
addError(msg,index);
}
//
// prepare for next certificate
//
if (i != n)
{
if (cert != null && cert.getVersion() == 1)
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.noCACert");
addError(msg,index);
}
// k)
BasicConstraints bc;
try
{
bc = BasicConstraints.getInstance(getExtensionValue(cert,
BASIC_CONSTRAINTS));
if (bc != null)
{
if (!bc.isCA())
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.noCACert");
addError(msg,index);
}
}
else
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.noBasicConstraints");
addError(msg,index);
}
}
catch (AnnotatedException ae)
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.errorProcesingBC");
addError(msg,index);
}
// n)
boolean[] _usage = cert.getKeyUsage();
if ((_usage != null) && !_usage[KEY_CERT_SIGN])
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.noCertSign");
addError(msg,index);
}
} // if
// set signing certificate for next round
sign = cert;
// c)
workingIssuerName = cert.getSubjectX500Principal();
// d) e) f)
try
{
workingPublicKey = getNextWorkingKey(certs, index);
workingAlgId = getAlgorithmIdentifier(workingPublicKey);
workingPublicKeyAlgorithm = workingAlgId.getObjectId();
workingPublicKeyParameters = workingAlgId.getParameters();
}
catch (CertPathValidatorException ex)
{
ErrorBundle msg = new ErrorBundle(RESOURCE_NAME,"CertPathReviewer.pubKeyError");
addError(msg,index);
workingAlgId = null;
workingPublicKeyAlgorithm = null;
workingPublicKeyParameters = null;
}