Path: blob/master/src/java.base/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java
41161 views
/*1* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.provider.certpath;2627import java.io.*;28import java.net.URI;29import java.security.*;30import java.security.cert.*;31import javax.security.auth.x500.X500Principal;32import java.util.*;3334import sun.security.util.Debug;35import sun.security.util.Event;36import sun.security.validator.Validator;37import static sun.security.x509.PKIXExtensions.*;38import sun.security.x509.*;3940/**41* Class to obtain CRLs via the CRLDistributionPoints extension.42* Note that the functionality of this class must be explicitly enabled43* via a system property, see the USE_CRLDP variable below.44*45* This class uses the URICertStore class to fetch CRLs. The URICertStore46* class also implements CRL caching: see the class description for more47* information.48*49* @author Andreas Sterbenz50* @author Sean Mullan51* @since 1.4.252*/53public class DistributionPointFetcher {5455private static final Debug debug = Debug.getInstance("certpath");5657private static final boolean[] ALL_REASONS =58{true, true, true, true, true, true, true, true, true};5960/**61* Private instantiation only.62*/63private DistributionPointFetcher() {}6465/**66* Return the X509CRLs matching this selector. The selector must be67* an X509CRLSelector with certificateChecking set.68*/69public static Collection<X509CRL> getCRLs(X509CRLSelector selector,70boolean signFlag, PublicKey prevKey, String provider,71List<CertStore> certStores, boolean[] reasonsMask,72Set<TrustAnchor> trustAnchors, Date validity, String variant)73throws CertStoreException74{75return getCRLs(selector, signFlag, prevKey, null, provider, certStores,76reasonsMask, trustAnchors, validity, variant, null);77}78/**79* Return the X509CRLs matching this selector. The selector must be80* an X509CRLSelector with certificateChecking set.81*/82// Called by com.sun.deploy.security.RevocationChecker83public static Collection<X509CRL> getCRLs(X509CRLSelector selector,84boolean signFlag,85PublicKey prevKey,86String provider,87List<CertStore> certStores,88boolean[] reasonsMask,89Set<TrustAnchor> trustAnchors,90Date validity)91throws CertStoreException92{93if (trustAnchors.isEmpty()) {94throw new CertStoreException(95"at least one TrustAnchor must be specified");96}97TrustAnchor anchor = trustAnchors.iterator().next();98return getCRLs(selector, signFlag, prevKey, null, provider, certStores,99reasonsMask, trustAnchors, validity,100Validator.VAR_PLUGIN_CODE_SIGNING, anchor);101}102103/**104* Return the X509CRLs matching this selector. The selector must be105* an X509CRLSelector with certificateChecking set.106*/107public static Collection<X509CRL> getCRLs(X509CRLSelector selector,108boolean signFlag,109PublicKey prevKey,110X509Certificate prevCert,111String provider,112List<CertStore> certStores,113boolean[] reasonsMask,114Set<TrustAnchor> trustAnchors,115Date validity,116String variant,117TrustAnchor anchor)118throws CertStoreException119{120X509Certificate cert = selector.getCertificateChecking();121if (cert == null) {122return Collections.emptySet();123}124try {125X509CertImpl certImpl = X509CertImpl.toImpl(cert);126if (debug != null) {127debug.println("DistributionPointFetcher.getCRLs: Checking "128+ "CRLDPs for " + certImpl.getSubjectX500Principal());129}130CRLDistributionPointsExtension ext =131certImpl.getCRLDistributionPointsExtension();132if (ext == null) {133if (debug != null) {134debug.println("No CRLDP ext");135}136return Collections.emptySet();137}138List<DistributionPoint> points =139ext.get(CRLDistributionPointsExtension.POINTS);140Set<X509CRL> results = new HashSet<>();141for (Iterator<DistributionPoint> t = points.iterator();142t.hasNext() && !Arrays.equals(reasonsMask, ALL_REASONS); ) {143DistributionPoint point = t.next();144Collection<X509CRL> crls = getCRLs(selector, certImpl,145point, reasonsMask, signFlag, prevKey, prevCert, provider,146certStores, trustAnchors, validity, variant, anchor);147results.addAll(crls);148}149if (debug != null) {150debug.println("Returning " + results.size() + " CRLs");151}152return results;153} catch (CertificateException | IOException e) {154return Collections.emptySet();155}156}157158/**159* Download CRLs from the given distribution point, verify and return them.160* See the top of the class for current limitations.161*162* @throws CertStoreException if there is an error retrieving the CRLs163* from one of the GeneralNames and no other CRLs are retrieved from164* the other GeneralNames. If more than one GeneralName throws an165* exception then the one from the last GeneralName is thrown.166*/167private static Collection<X509CRL> getCRLs(X509CRLSelector selector,168X509CertImpl certImpl, DistributionPoint point, boolean[] reasonsMask,169boolean signFlag, PublicKey prevKey, X509Certificate prevCert,170String provider, List<CertStore> certStores,171Set<TrustAnchor> trustAnchors, Date validity, String variant,172TrustAnchor anchor)173throws CertStoreException {174175// check for full name176GeneralNames fullName = point.getFullName();177if (fullName == null) {178// check for relative name179RDN relativeName = point.getRelativeName();180if (relativeName == null) {181return Collections.emptySet();182}183try {184GeneralNames crlIssuers = point.getCRLIssuer();185if (crlIssuers == null) {186fullName = getFullNames187((X500Name) certImpl.getIssuerDN(), relativeName);188} else {189// should only be one CRL Issuer190if (crlIssuers.size() != 1) {191return Collections.emptySet();192} else {193fullName = getFullNames194((X500Name) crlIssuers.get(0).getName(), relativeName);195}196}197} catch (IOException ioe) {198return Collections.emptySet();199}200}201Collection<X509CRL> possibleCRLs = new ArrayList<>();202CertStoreException savedCSE = null;203for (Iterator<GeneralName> t = fullName.iterator(); t.hasNext(); ) {204try {205GeneralName name = t.next();206if (name.getType() == GeneralNameInterface.NAME_DIRECTORY) {207X500Name x500Name = (X500Name) name.getName();208possibleCRLs.addAll(209getCRLs(x500Name, certImpl.getIssuerX500Principal(),210certStores));211} else if (name.getType() == GeneralNameInterface.NAME_URI) {212URIName uriName = (URIName)name.getName();213X509CRL crl = getCRL(uriName);214if (crl != null) {215possibleCRLs.add(crl);216}217}218} catch (CertStoreException cse) {219savedCSE = cse;220}221}222// only throw CertStoreException if no CRLs are retrieved223if (possibleCRLs.isEmpty() && savedCSE != null) {224throw savedCSE;225}226227Collection<X509CRL> crls = new ArrayList<>(2);228for (X509CRL crl : possibleCRLs) {229try {230// make sure issuer is not set231// we check the issuer in verifyCRLs method232selector.setIssuerNames(null);233if (selector.match(crl) && verifyCRL(certImpl, point, crl,234reasonsMask, signFlag, prevKey, prevCert, provider,235trustAnchors, certStores, validity, variant, anchor)) {236crls.add(crl);237}238} catch (IOException | CRLException e) {239// don't add the CRL240if (debug != null) {241debug.println("Exception verifying CRL: " + e.getMessage());242e.printStackTrace();243}244}245}246return crls;247}248249/**250* Download CRL from given URI.251*/252private static X509CRL getCRL(URIName name) throws CertStoreException {253URI uri = name.getURI();254if (debug != null) {255debug.println("Trying to fetch CRL from DP " + uri);256}257258Event.report(Event.ReporterCategory.CRLCHECK, "event.crl.check", uri.toString());259CertStore ucs = null;260try {261ucs = URICertStore.getInstance(new URICertStoreParameters(uri));262} catch (InvalidAlgorithmParameterException |263NoSuchAlgorithmException e) {264if (debug != null) {265debug.println("Can't create URICertStore: " + e.getMessage());266}267return null;268}269270Collection<? extends CRL> crls = ucs.getCRLs(null);271if (crls.isEmpty()) {272return null;273} else {274return (X509CRL) crls.iterator().next();275}276}277278/**279* Fetch CRLs from certStores.280*281* @throws CertStoreException if there is an error retrieving the CRLs from282* one of the CertStores and no other CRLs are retrieved from283* the other CertStores. If more than one CertStore throws an284* exception then the one from the last CertStore is thrown.285*/286private static Collection<X509CRL> getCRLs(X500Name name,287X500Principal certIssuer,288List<CertStore> certStores)289throws CertStoreException290{291if (debug != null) {292debug.println("Trying to fetch CRL from DP " + name);293}294X509CRLSelector xcs = new X509CRLSelector();295xcs.addIssuer(name.asX500Principal());296xcs.addIssuer(certIssuer);297Collection<X509CRL> crls = new ArrayList<>();298CertStoreException savedCSE = null;299for (CertStore store : certStores) {300try {301for (CRL crl : store.getCRLs(xcs)) {302crls.add((X509CRL)crl);303}304} catch (CertStoreException cse) {305if (debug != null) {306debug.println("Exception while retrieving " +307"CRLs: " + cse);308cse.printStackTrace();309}310savedCSE = new PKIX.CertStoreTypeException(store.getType(),cse);311}312}313// only throw CertStoreException if no CRLs are retrieved314if (crls.isEmpty() && savedCSE != null) {315throw savedCSE;316} else {317return crls;318}319}320321/**322* Verifies a CRL for the given certificate's Distribution Point to323* ensure it is appropriate for checking the revocation status.324*325* @param certImpl the certificate whose revocation status is being checked326* @param point one of the distribution points of the certificate327* @param crl the CRL328* @param reasonsMask the interim reasons mask329* @param signFlag true if prevKey can be used to verify the CRL330* @param prevKey the public key that verifies the certificate's signature331* @param prevCert the certificate whose public key verifies332* {@code certImpl}'s signature333* @param provider the Signature provider to use334* @param trustAnchors a {@code Set} of {@code TrustAnchor}s335* @param certStores a {@code List} of {@code CertStore}s to be used in336* finding certificates and CRLs337* @param validity the time for which the validity of the CRL issuer's338* certification path should be determined339* @return true if ok, false if not340*/341static boolean verifyCRL(X509CertImpl certImpl, DistributionPoint point,342X509CRL crl, boolean[] reasonsMask, boolean signFlag,343PublicKey prevKey, X509Certificate prevCert, String provider,344Set<TrustAnchor> trustAnchors, List<CertStore> certStores,345Date validity, String variant, TrustAnchor anchor)346throws CRLException, IOException {347348if (debug != null) {349debug.println("DistributionPointFetcher.verifyCRL: " +350"checking revocation status for" +351"\n SN: " + Debug.toHexString(certImpl.getSerialNumber()) +352"\n Subject: " + certImpl.getSubjectX500Principal() +353"\n Issuer: " + certImpl.getIssuerX500Principal());354}355356boolean indirectCRL = false;357X509CRLImpl crlImpl = X509CRLImpl.toImpl(crl);358IssuingDistributionPointExtension idpExt =359crlImpl.getIssuingDistributionPointExtension();360X500Name certIssuer = (X500Name) certImpl.getIssuerDN();361X500Name crlIssuer = (X500Name) crlImpl.getIssuerDN();362363// if crlIssuer is set, verify that it matches the issuer of the364// CRL and the CRL contains an IDP extension with the indirectCRL365// boolean asserted. Otherwise, verify that the CRL issuer matches the366// certificate issuer.367GeneralNames pointCrlIssuers = point.getCRLIssuer();368X500Name pointCrlIssuer = null;369if (pointCrlIssuers != null) {370if (idpExt == null ||371((Boolean) idpExt.get372(IssuingDistributionPointExtension.INDIRECT_CRL)).equals373(Boolean.FALSE)) {374return false;375}376boolean match = false;377for (Iterator<GeneralName> t = pointCrlIssuers.iterator();378!match && t.hasNext(); ) {379GeneralNameInterface name = t.next().getName();380if (crlIssuer.equals(name) == true) {381pointCrlIssuer = (X500Name) name;382match = true;383}384}385if (match == false) {386return false;387}388389// we accept the case that a CRL issuer provide status390// information for itself.391if (issues(certImpl, crlImpl, provider)) {392// reset the public key used to verify the CRL's signature393prevKey = certImpl.getPublicKey();394} else {395indirectCRL = true;396}397} else if (crlIssuer.equals(certIssuer) == false) {398if (debug != null) {399debug.println("crl issuer does not equal cert issuer.\n" +400"crl issuer: " + crlIssuer + "\n" +401"cert issuer: " + certIssuer);402}403return false;404} else {405// in case of self-issued indirect CRL issuer.406KeyIdentifier certAKID = certImpl.getAuthKeyId();407KeyIdentifier crlAKID = crlImpl.getAuthKeyId();408409if (certAKID == null || crlAKID == null) {410// cannot recognize indirect CRL without AKID411412// we accept the case that a CRL issuer provide status413// information for itself.414if (issues(certImpl, crlImpl, provider)) {415// reset the public key used to verify the CRL's signature416prevKey = certImpl.getPublicKey();417}418} else if (!certAKID.equals(crlAKID)) {419// we accept the case that a CRL issuer provide status420// information for itself.421if (issues(certImpl, crlImpl, provider)) {422// reset the public key used to verify the CRL's signature423prevKey = certImpl.getPublicKey();424} else {425indirectCRL = true;426}427}428}429430if (!indirectCRL && !signFlag) {431// cert's key cannot be used to verify the CRL432return false;433}434435if (idpExt != null) {436DistributionPointName idpPoint = (DistributionPointName)437idpExt.get(IssuingDistributionPointExtension.POINT);438if (idpPoint != null) {439GeneralNames idpNames = idpPoint.getFullName();440if (idpNames == null) {441RDN relativeName = idpPoint.getRelativeName();442if (relativeName == null) {443if (debug != null) {444debug.println("IDP must be relative or full DN");445}446return false;447}448if (debug != null) {449debug.println("IDP relativeName:" + relativeName);450}451idpNames = getFullNames(crlIssuer, relativeName);452}453// if the DP name is present in the IDP CRL extension and the454// DP field is present in the DP, then verify that one of the455// names in the IDP matches one of the names in the DP456if (point.getFullName() != null ||457point.getRelativeName() != null) {458GeneralNames pointNames = point.getFullName();459if (pointNames == null) {460RDN relativeName = point.getRelativeName();461if (relativeName == null) {462if (debug != null) {463debug.println("DP must be relative or full DN");464}465return false;466}467if (debug != null) {468debug.println("DP relativeName:" + relativeName);469}470if (indirectCRL) {471if (pointCrlIssuers.size() != 1) {472// RFC 5280: there must be only 1 CRL issuer473// name when relativeName is present474if (debug != null) {475debug.println("must only be one CRL " +476"issuer when relative name present");477}478return false;479}480pointNames = getFullNames481(pointCrlIssuer, relativeName);482} else {483pointNames = getFullNames(certIssuer, relativeName);484}485}486boolean match = false;487for (Iterator<GeneralName> i = idpNames.iterator();488!match && i.hasNext(); ) {489GeneralNameInterface idpName = i.next().getName();490if (debug != null) {491debug.println("idpName: " + idpName);492}493for (Iterator<GeneralName> p = pointNames.iterator();494!match && p.hasNext(); ) {495GeneralNameInterface pointName = p.next().getName();496if (debug != null) {497debug.println("pointName: " + pointName);498}499match = idpName.equals(pointName);500}501}502if (!match) {503if (debug != null) {504debug.println("IDP name does not match DP name");505}506return false;507}508// if the DP name is present in the IDP CRL extension and the509// DP field is absent from the DP, then verify that one of the510// names in the IDP matches one of the names in the crlIssuer511// field of the DP512} else {513// verify that one of the names in the IDP matches one of514// the names in the cRLIssuer of the cert's DP515boolean match = false;516for (Iterator<GeneralName> t = pointCrlIssuers.iterator();517!match && t.hasNext(); ) {518GeneralNameInterface crlIssuerName = t.next().getName();519for (Iterator<GeneralName> i = idpNames.iterator();520!match && i.hasNext(); ) {521GeneralNameInterface idpName = i.next().getName();522match = crlIssuerName.equals(idpName);523}524}525if (!match) {526return false;527}528}529}530531// if the onlyContainsUserCerts boolean is asserted, verify that the532// cert is not a CA cert533Boolean b = (Boolean)534idpExt.get(IssuingDistributionPointExtension.ONLY_USER_CERTS);535if (b.equals(Boolean.TRUE) && certImpl.getBasicConstraints() != -1) {536if (debug != null) {537debug.println("cert must be a EE cert");538}539return false;540}541542// if the onlyContainsCACerts boolean is asserted, verify that the543// cert is a CA cert544b = (Boolean)545idpExt.get(IssuingDistributionPointExtension.ONLY_CA_CERTS);546if (b.equals(Boolean.TRUE) && certImpl.getBasicConstraints() == -1) {547if (debug != null) {548debug.println("cert must be a CA cert");549}550return false;551}552553// verify that the onlyContainsAttributeCerts boolean is not554// asserted555b = (Boolean) idpExt.get556(IssuingDistributionPointExtension.ONLY_ATTRIBUTE_CERTS);557if (b.equals(Boolean.TRUE)) {558if (debug != null) {559debug.println("cert must not be an AA cert");560}561return false;562}563}564565// compute interim reasons mask566boolean[] interimReasonsMask = new boolean[9];567ReasonFlags reasons = null;568if (idpExt != null) {569reasons = (ReasonFlags)570idpExt.get(IssuingDistributionPointExtension.REASONS);571}572573boolean[] pointReasonFlags = point.getReasonFlags();574if (reasons != null) {575if (pointReasonFlags != null) {576// set interim reasons mask to the intersection of577// reasons in the DP and onlySomeReasons in the IDP578boolean[] idpReasonFlags = reasons.getFlags();579for (int i = 0; i < interimReasonsMask.length; i++) {580interimReasonsMask[i] =581(i < idpReasonFlags.length && idpReasonFlags[i]) &&582(i < pointReasonFlags.length && pointReasonFlags[i]);583}584} else {585// set interim reasons mask to the value of586// onlySomeReasons in the IDP (and clone it since we may587// modify it)588interimReasonsMask = reasons.getFlags().clone();589}590} else if (idpExt == null || reasons == null) {591if (pointReasonFlags != null) {592// set interim reasons mask to the value of DP reasons593interimReasonsMask = pointReasonFlags.clone();594} else {595// set interim reasons mask to the special value all-reasons596Arrays.fill(interimReasonsMask, true);597}598}599600// verify that interim reasons mask includes one or more reasons601// not included in the reasons mask602boolean oneOrMore = false;603for (int i = 0; i < interimReasonsMask.length && !oneOrMore; i++) {604if (interimReasonsMask[i] &&605!(i < reasonsMask.length && reasonsMask[i]))606{607oneOrMore = true;608}609}610if (!oneOrMore) {611return false;612}613614// Obtain and validate the certification path for the complete615// CRL issuer (if indirect CRL). If a key usage extension is present616// in the CRL issuer's certificate, verify that the cRLSign bit is set.617if (indirectCRL) {618X509CertSelector certSel = new X509CertSelector();619certSel.setSubject(crlIssuer.asX500Principal());620boolean[] crlSign = {false,false,false,false,false,false,true};621certSel.setKeyUsage(crlSign);622623// Currently by default, forward builder does not enable624// subject/authority key identifier identifying for target625// certificate, instead, it only compares the CRL issuer and626// the target certificate subject. If the certificate of the627// delegated CRL issuer is a self-issued certificate, the628// builder is unable to find the proper CRL issuer by issuer629// name only, there is a potential dead loop on finding the630// proper issuer. It is of great help to narrow the target631// scope down to aware of authority key identifiers in the632// selector, for the purposes of breaking the dead loop.633AuthorityKeyIdentifierExtension akidext =634crlImpl.getAuthKeyIdExtension();635if (akidext != null) {636byte[] kid = akidext.getEncodedKeyIdentifier();637if (kid != null) {638certSel.setSubjectKeyIdentifier(kid);639}640641SerialNumber asn = (SerialNumber)akidext.get(642AuthorityKeyIdentifierExtension.SERIAL_NUMBER);643if (asn != null) {644certSel.setSerialNumber(asn.getNumber());645}646// the subject criterion will be set by builder automatically.647}648649// By now, we have validated the previous certificate, so we can650// trust it during the validation of the CRL issuer.651// In addition to the performance improvement, another benefit is to652// break the dead loop while looking for the issuer back and forth653// between the delegated self-issued certificate and its issuer.654Set<TrustAnchor> newTrustAnchors = new HashSet<>(trustAnchors);655656if (prevKey != null) {657// Add the previous certificate as a trust anchor.658// If prevCert is not null, we want to construct a TrustAnchor659// using the cert object because when the certpath for the CRL660// is built later, the CertSelector will make comparisons with661// the TrustAnchor's trustedCert member rather than its pubKey.662TrustAnchor temporary;663if (prevCert != null) {664temporary = new TrustAnchor(prevCert, null);665} else {666X500Principal principal = certImpl.getIssuerX500Principal();667temporary = new TrustAnchor(principal, prevKey, null);668}669newTrustAnchors.add(temporary);670}671672PKIXBuilderParameters params = null;673try {674params = new PKIXBuilderParameters(newTrustAnchors, certSel);675} catch (InvalidAlgorithmParameterException iape) {676throw new CRLException(iape);677}678params.setCertStores(certStores);679params.setSigProvider(provider);680params.setDate(validity);681try {682CertPathBuilder builder = CertPathBuilder.getInstance("PKIX");683PKIXCertPathBuilderResult result =684(PKIXCertPathBuilderResult) builder.build(params);685prevKey = result.getPublicKey();686} catch (GeneralSecurityException e) {687throw new CRLException(e);688}689}690691// check the crl signature algorithm692try {693AlgorithmChecker.check(prevKey, crl, variant, anchor);694} catch (CertPathValidatorException cpve) {695if (debug != null) {696debug.println("CRL signature algorithm check failed: " + cpve);697}698return false;699}700701// validate the signature on the CRL702try {703crl.verify(prevKey, provider);704} catch (GeneralSecurityException e) {705if (debug != null) {706debug.println("CRL signature failed to verify");707}708return false;709}710711// reject CRL if any unresolved critical extensions remain in the CRL.712Set<String> unresCritExts = crl.getCriticalExtensionOIDs();713// remove any that we have processed714if (unresCritExts != null) {715unresCritExts.remove(IssuingDistributionPoint_Id.toString());716if (!unresCritExts.isEmpty()) {717if (debug != null) {718debug.println("Unrecognized critical extension(s) in CRL: "719+ unresCritExts);720for (String ext : unresCritExts) {721debug.println(ext);722}723}724return false;725}726}727728// update reasonsMask729for (int i = 0; i < reasonsMask.length; i++) {730reasonsMask[i] = reasonsMask[i] ||731(i < interimReasonsMask.length && interimReasonsMask[i]);732}733734return true;735}736737/**738* Append relative name to the issuer name and return a new739* GeneralNames object.740*/741private static GeneralNames getFullNames(X500Name issuer, RDN rdn)742throws IOException743{744List<RDN> rdns = new ArrayList<>(issuer.rdns());745rdns.add(rdn);746X500Name fullName = new X500Name(rdns.toArray(new RDN[0]));747GeneralNames fullNames = new GeneralNames();748fullNames.add(new GeneralName(fullName));749return fullNames;750}751752/**753* Verifies whether a CRL is issued by a certain certificate754*755* @param cert the certificate756* @param crl the CRL to be verified757* @param provider the name of the signature provider758*/759private static boolean issues(X509CertImpl cert, X509CRLImpl crl,760String provider) throws IOException761{762boolean matched = false;763764AdaptableX509CertSelector issuerSelector =765new AdaptableX509CertSelector();766767// check certificate's key usage768boolean[] usages = cert.getKeyUsage();769if (usages != null) {770usages[6] = true; // cRLSign771issuerSelector.setKeyUsage(usages);772}773774// check certificate's subject775X500Principal crlIssuer = crl.getIssuerX500Principal();776issuerSelector.setSubject(crlIssuer);777778/*779* Facilitate certification path construction with authority780* key identifier and subject key identifier.781*782* In practice, conforming CAs MUST use the key identifier method,783* and MUST include authority key identifier extension in all CRLs784* issued. [section 5.2.1, RFC 5280]785*/786AuthorityKeyIdentifierExtension crlAKID = crl.getAuthKeyIdExtension();787issuerSelector.setSkiAndSerialNumber(crlAKID);788789matched = issuerSelector.match(cert);790791// if AKID is unreliable, verify the CRL signature with the cert792if (matched && (crlAKID == null ||793cert.getAuthorityKeyIdentifierExtension() == null)) {794try {795crl.verify(cert.getPublicKey(), provider);796matched = true;797} catch (GeneralSecurityException e) {798matched = false;799}800}801802return matched;803}804}805806807