TrustAnchor
object if found or
* null
if not.
* @throws AnnotatedException if a TrustAnchor was found but the signature verification
* on the given certificate has thrown an exception.
*/
protected static TrustAnchor findTrustAnchor(
X509Certificate cert,
Set trustAnchors)
throws AnnotatedException
{
return findTrustAnchor(cert, trustAnchors, null);
}
/**
* Search the given Set of TrustAnchor's for one that is the
* issuer of the given X509 certificate. Uses the specified
* provider for signature verification, or the default provider
* if null.
*
* @param cert the X509 certificate
* @param trustAnchors a Set of TrustAnchor's
* @param sigProvider the provider to use for signature verification
* @return the TrustAnchor
object if found or
* null
if not.
* @throws AnnotatedException if a TrustAnchor was found but the signature verification
* on the given certificate has thrown an exception.
*/
protected static TrustAnchor findTrustAnchor(
X509Certificate cert,
Set trustAnchors,
String sigProvider)
throws AnnotatedException
{
TrustAnchor trust = null;
PublicKey trustPublicKey = null;
Exception invalidKeyEx = null;
X509CertSelector certSelectX509 = new X509CertSelector();
X500Name certIssuer = PrincipalUtils.getEncodedIssuerPrincipal(cert);
try
{
certSelectX509.setSubject(certIssuer.getEncoded());
}
catch (IOException ex)
{
throw new AnnotatedException("Cannot set subject search criteria for trust anchor.", ex);
}
Iterator iter = trustAnchors.iterator();
while (iter.hasNext() && trust == null)
{
trust = (TrustAnchor)iter.next();
if (trust.getTrustedCert() != null)
{
if (certSelectX509.match(trust.getTrustedCert()))
{
trustPublicKey = trust.getTrustedCert().getPublicKey();
}
else
{
trust = null;
}
}
else if (trust.getCAName() != null
&& trust.getCAPublicKey() != null)
{
try
{
X500Name caName = PrincipalUtils.getCA(trust);
if (certIssuer.equals(caName))
{
trustPublicKey = trust.getCAPublicKey();
}
else
{
trust = null;
}
}
catch (IllegalArgumentException ex)
{
trust = null;
}
}
else
{
trust = null;
}
if (trustPublicKey != null)
{
try
{
verifyX509Certificate(cert, trustPublicKey, sigProvider);
}
catch (Exception ex)
{
invalidKeyEx = ex;
trust = null;
trustPublicKey = null;
}
}
}
if (trust == null && invalidKeyEx != null)
{
throw new AnnotatedException("TrustAnchor found but certificate validation failed.", invalidKeyEx);
}
return trust;
}
static Listnull
.
*/
protected static Collection findCertificates(PKIXCertStoreSelector certSelect,
List certStores)
throws AnnotatedException
{
Set certs = new LinkedHashSet();
Iterator iter = certStores.iterator();
while (iter.hasNext())
{
Object obj = iter.next();
// BEGIN android-removed
// if (obj instanceof X509Store)
// {
// X509Store certStore = (X509Store)obj;
// try
// {
// certs.addAll(certStore.getMatches(certSelect));
// }
// catch (StoreException e)
// {
// throw new AnnotatedException(
// "Problem while picking certificates from X.509 store.", e);
// }
// }
// else
// END android-removed
{
CertStore certStore = (CertStore)obj;
try
{
certs.addAll(PKIXCertStoreSelector.getCertificates(certSelect, certStore));
}
catch (CertStoreException e)
{
throw new AnnotatedException(
"Problem while picking certificates from certificate store.",
e);
}
}
}
return certs;
}
static Listselector
.
*
* The issuerPrincipals
are a collection with a single
* X500Name
for X509Certificate
s.
*
issuerPrincipals
does not
* contain only X500Name
s.
*/
protected static void getCRLIssuersFromDistributionPoint(
DistributionPoint dp,
Collection issuerPrincipals,
X509CRLSelector selector)
throws AnnotatedException
{
List issuers = new ArrayList();
// indirect CRL
if (dp.getCRLIssuer() != null)
{
GeneralName genNames[] = dp.getCRLIssuer().getNames();
// look for a DN
for (int j = 0; j < genNames.length; j++)
{
if (genNames[j].getTagNo() == GeneralName.directoryName)
{
try
{
issuers.add(X500Name.getInstance(genNames[j].getName()
.toASN1Primitive().getEncoded()));
}
catch (IOException e)
{
throw new AnnotatedException(
"CRL issuer information from distribution point cannot be decoded.",
e);
}
}
}
}
else
{
/*
* certificate issuer is CRL issuer, distributionPoint field MUST be
* present.
*/
if (dp.getDistributionPoint() == null)
{
throw new AnnotatedException(
"CRL issuer is omitted from distribution point but no distributionPoint field present.");
}
// add and check issuer principals
for (Iterator it = issuerPrincipals.iterator(); it.hasNext(); )
{
issuers.add(it.next());
}
}
// TODO: is not found although this should correctly add the rel name. selector of Sun is buggy here or PKI test case is invalid
// distributionPoint
// if (dp.getDistributionPoint() != null)
// {
// // look for nameRelativeToCRLIssuer
// if (dp.getDistributionPoint().getType() == DistributionPointName.NAME_RELATIVE_TO_CRL_ISSUER)
// {
// // append fragment to issuer, only one
// // issuer can be there, if this is given
// if (issuers.size() != 1)
// {
// throw new AnnotatedException(
// "nameRelativeToCRLIssuer field is given but more than one CRL issuer is given.");
// }
// ASN1Encodable relName = dp.getDistributionPoint().getName();
// Iterator it = issuers.iterator();
// List issuersTemp = new ArrayList(issuers.size());
// while (it.hasNext())
// {
// Enumeration e = null;
// try
// {
// e = ASN1Sequence.getInstance(
// new ASN1InputStream(((X500Principal) it.next())
// .getEncoded()).readObject()).getObjects();
// }
// catch (IOException ex)
// {
// throw new AnnotatedException(
// "Cannot decode CRL issuer information.", ex);
// }
// ASN1EncodableVector v = new ASN1EncodableVector();
// while (e.hasMoreElements())
// {
// v.add((ASN1Encodable) e.nextElement());
// }
// v.add(relName);
// issuersTemp.add(new X500Principal(new DERSequence(v)
// .getDEREncoded()));
// }
// issuers.clear();
// issuers.addAll(issuersTemp);
// }
// }
Iterator it = issuers.iterator();
while (it.hasNext())
{
try
{
selector.addIssuerName(((X500Name)it.next()).getEncoded());
}
catch (IOException ex)
{
throw new AnnotatedException(
"Cannot decode CRL issuer information.", ex);
}
}
}
private static BigInteger getSerialNumber(
Object cert)
{
return ((X509Certificate)cert).getSerialNumber();
}
protected static void getCertStatus(
Date validDate,
X509CRL crl,
Object cert,
CertStatus certStatus)
throws AnnotatedException
{
X509CRLEntry crl_entry = null;
boolean isIndirect;
try
{
isIndirect = X509CRLObject.isIndirectCRL(crl);
}
catch (CRLException exception)
{
throw new AnnotatedException("Failed check for indirect CRL.", exception);
}
if (isIndirect)
{
crl_entry = crl.getRevokedCertificate(getSerialNumber(cert));
if (crl_entry == null)
{
return;
}
// BEGIN android-removed
// X500Name certIssuer = X500Name.getInstance(crl_entry.getCertificateIssuer().getEncoded());
// END android-removed
// BEGIN android-added
// The original code throws null pointer exception for OpenSSLX509CRL,
// which uses the implementation for getCertificateIssuer() in X509CRL, method
// whose reference implementation has the following JavaDoc: "If the certificate
// issuer is also the CRL issuer, this method returns null."
X500Name certIssuer = null;
X500Principal certificateIssuerPrincipal = crl_entry.getCertificateIssuer();
if (certificateIssuerPrincipal != null) {
certIssuer = X500Name.getInstance(certificateIssuerPrincipal.getEncoded());
}
// END android-added
if (certIssuer == null)
{
certIssuer = PrincipalUtils.getIssuerPrincipal(crl);
}
if (! PrincipalUtils.getEncodedIssuerPrincipal(cert).equals(certIssuer))
{
return;
}
}
else if (! PrincipalUtils.getEncodedIssuerPrincipal(cert).equals(PrincipalUtils.getIssuerPrincipal(crl)))
{
return; // not for our issuer, ignore
}
else
{
crl_entry = crl.getRevokedCertificate(getSerialNumber(cert));
if (crl_entry == null)
{
return;
}
}
ASN1Enumerated reasonCode = null;
if (crl_entry.hasExtensions())
{
try
{
reasonCode = ASN1Enumerated
.getInstance(CertPathValidatorUtilities
.getExtensionValue(crl_entry,
Extension.reasonCode.getId()));
}
catch (Exception e)
{
throw new AnnotatedException(
"Reason code CRL entry extension could not be decoded.",
e);
}
}
// for reason keyCompromise, caCompromise, aACompromise or
// unspecified
if (!(validDate.getTime() < crl_entry.getRevocationDate().getTime())
|| reasonCode == null
|| reasonCode.getValue().intValue() == 0
|| reasonCode.getValue().intValue() == 1
|| reasonCode.getValue().intValue() == 2
|| reasonCode.getValue().intValue() == 8)
{
// (i) or (j) (1)
if (reasonCode != null)
{
certStatus.setCertStatus(reasonCode.getValue().intValue());
}
// (i) or (j) (2)
else
{
certStatus.setCertStatus(CRLReason.unspecified);
}
certStatus.setRevocationDate(crl_entry.getRevocationDate());
}
}
/**
* Fetches delta CRLs according to RFC 3280 section 5.2.4.
*
* @param validityDate The date for which the delta CRLs must be valid.
* @param completeCRL The complete CRL the delta CRL is for.
* @return A Set
of X509CRL
s with delta CRLs.
* @throws AnnotatedException if an exception occurs while picking the delta
* CRLs.
*/
protected static Set getDeltaCRLs(Date validityDate,
X509CRL completeCRL, ListX509Certificate
for
* which the CRL should be searched.
* @param currentDate The date for which the delta CRLs must be valid.
* @param paramsPKIX The extended PKIX parameters.
* @return A Set
of X509CRL
s with complete
* CRLs.
* @throws AnnotatedException if an exception occurs while picking the CRLs
* or no CRLs are found.
*/
protected static Set getCompleteCRLs(DistributionPoint dp, Object cert,
Date currentDate, PKIXExtendedParameters paramsPKIX)
throws AnnotatedException
{
X509CRLSelector baseCrlSelect = new X509CRLSelector();
try
{
Set issuers = new HashSet();
issuers.add(PrincipalUtils.getEncodedIssuerPrincipal(cert));
CertPathValidatorUtilities.getCRLIssuersFromDistributionPoint(dp, issuers, baseCrlSelect);
}
catch (AnnotatedException e)
{
throw new AnnotatedException(
"Could not get issuer information from distribution point.", e);
}
if (cert instanceof X509Certificate)
{
baseCrlSelect.setCertificateChecking((X509Certificate)cert);
}
PKIXCRLStoreSelector crlSelect = new PKIXCRLStoreSelector.Builder(baseCrlSelect).setCompleteCRLEnabled(true).build();
Date validityDate = currentDate;
if (paramsPKIX.getDate() != null)
{
validityDate = paramsPKIX.getDate();
}
Set crls = CRL_UTIL.findCRLs(crlSelect, validityDate, paramsPKIX.getCertStores(), paramsPKIX.getCRLStores());
checkCRLsNotEmpty(crls, cert);
return crls;
}
protected static Date getValidCertDateFromValidityModel(
PKIXExtendedParameters paramsPKIX, CertPath certPath, int index)
throws AnnotatedException
{
if (paramsPKIX.getValidityModel() == PKIXExtendedParameters.CHAIN_VALIDITY_MODEL)
{
// if end cert use given signing/encryption/... time
if (index <= 0)
{
return CertPathValidatorUtilities.getValidDate(paramsPKIX);
// else use time when previous cert was created
}
else
{
if (index - 1 == 0)
{
ASN1GeneralizedTime dateOfCertgen = null;
try
{
byte[] extBytes = ((X509Certificate)certPath.getCertificates().get(index - 1)).getExtensionValue(ISISMTTObjectIdentifiers.id_isismtt_at_dateOfCertGen.getId());
if (extBytes != null)
{
dateOfCertgen = ASN1GeneralizedTime.getInstance(ASN1Primitive.fromByteArray(extBytes));
}
}
catch (IOException e)
{
throw new AnnotatedException(
"Date of cert gen extension could not be read.");
}
catch (IllegalArgumentException e)
{
throw new AnnotatedException(
"Date of cert gen extension could not be read.");
}
if (dateOfCertgen != null)
{
try
{
return dateOfCertgen.getDate();
}
catch (ParseException e)
{
throw new AnnotatedException(
"Date from date of cert gen extension could not be parsed.",
e);
}
}
return ((X509Certificate)certPath.getCertificates().get(
index - 1)).getNotBefore();
}
else
{
return ((X509Certificate)certPath.getCertificates().get(
index - 1)).getNotBefore();
}
}
}
else
{
return getValidDate(paramsPKIX);
}
}
/**
* Return the next working key inheriting DSA parameters if necessary.
*
* This methods inherits DSA parameters from the indexed certificate or
* previous certificates in the certificate chain to the returned
* PublicKey
. The list is searched upwards, meaning the end
* certificate is at position 0 and previous certificates are following.
*
* If the indexed certificate does not contain a DSA key this method simply * returns the public key. If the DSA key already contains DSA parameters * the key is also only returned. *
* * @param certs The certification path. * @param index The index of the certificate which contains the public key * which should be extended with DSA parameters. * @return The public key of the certificate in list position *index
extended with DSA parameters if applicable.
* @throws AnnotatedException if DSA parameters cannot be inherited.
*/
protected static PublicKey getNextWorkingKey(List certs, int index, JcaJceHelper helper)
throws CertPathValidatorException
{
Certificate cert = (Certificate)certs.get(index);
PublicKey pubKey = cert.getPublicKey();
if (!(pubKey instanceof DSAPublicKey))
{
return pubKey;
}
DSAPublicKey dsaPubKey = (DSAPublicKey)pubKey;
if (dsaPubKey.getParams() != null)
{
return dsaPubKey;
}
for (int i = index + 1; i < certs.size(); i++)
{
X509Certificate parentCert = (X509Certificate)certs.get(i);
pubKey = parentCert.getPublicKey();
if (!(pubKey instanceof DSAPublicKey))
{
throw new CertPathValidatorException(
"DSA parameters cannot be inherited from previous certificate.");
}
DSAPublicKey prevDSAPubKey = (DSAPublicKey)pubKey;
if (prevDSAPubKey.getParams() == null)
{
continue;
}
DSAParams dsaParams = prevDSAPubKey.getParams();
DSAPublicKeySpec dsaPubKeySpec = new DSAPublicKeySpec(
dsaPubKey.getY(), dsaParams.getP(), dsaParams.getQ(), dsaParams.getG());
try
{
KeyFactory keyFactory = helper.createKeyFactory("DSA");
return keyFactory.generatePublic(dsaPubKeySpec);
}
catch (Exception exception)
{
throw new RuntimeException(exception.getMessage());
}
}
throw new CertPathValidatorException("DSA parameters cannot be inherited from previous certificate.");
}
/**
* Find the issuer certificates of a given certificate.
*
* @param cert The certificate for which an issuer should be found.
* @return A Collection
object containing the issuer
* X509Certificate
s. Never null
.
* @throws AnnotatedException if an error occurs.
*/
static Collection findIssuerCerts(
X509Certificate cert,
List