1 package org.bouncycastle.jce.provider;
2 
3 import java.io.ByteArrayOutputStream;
4 import java.io.IOException;
5 import java.math.BigInteger;
6 import java.net.URL;
7 import java.security.GeneralSecurityException;
8 import java.security.KeyFactory;
9 import java.security.PublicKey;
10 import java.security.cert.CRLException;
11 import java.security.cert.CertPath;
12 import java.security.cert.CertPathBuilderException;
13 import java.security.cert.CertPathValidatorException;
14 import java.security.cert.CertStore;
15 import java.security.cert.CertStoreException;
16 import java.security.cert.Certificate;
17 import java.security.cert.CertificateFactory;
18 import java.security.cert.CertificateParsingException;
19 import org.bouncycastle.jce.cert.PolicyQualifierInfo;
20 import org.bouncycastle.jce.cert.TrustAnchor;
21 import java.security.cert.X509CRL;
22 import java.security.cert.X509CRLEntry;
23 import java.security.cert.X509CRLSelector;
24 import java.security.cert.X509CertSelector;
25 import java.security.cert.X509Certificate;
26 import java.security.interfaces.DSAParams;
27 import java.security.interfaces.DSAPublicKey;
28 import java.security.spec.DSAPublicKeySpec;
29 import java.text.ParseException;
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.Date;
34 import java.util.Enumeration;
35 import java.util.HashSet;
36 import java.util.Iterator;
37 import java.util.HashSet;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Set;
41 
42 import org.bouncycastle.jce.X509Principal;
43 import org.bouncycastle.jce.PrincipalUtil;
44 
45 import org.bouncycastle.asn1.ASN1Encodable;
46 import org.bouncycastle.asn1.ASN1Enumerated;
47 import org.bouncycastle.asn1.ASN1GeneralizedTime;
48 import org.bouncycastle.asn1.ASN1Integer;
49 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
50 import org.bouncycastle.asn1.ASN1OctetString;
51 import org.bouncycastle.asn1.ASN1OutputStream;
52 import org.bouncycastle.asn1.ASN1Primitive;
53 import org.bouncycastle.asn1.ASN1Sequence;
54 import org.bouncycastle.asn1.ASN1String;
55 import org.bouncycastle.asn1.DEROctetString;
56 import org.bouncycastle.asn1.DERSequence;
57 import org.bouncycastle.asn1.isismtt.ISISMTTObjectIdentifiers;
58 import org.bouncycastle.asn1.x500.X500Name;
59 import org.bouncycastle.asn1.x500.style.RFC4519Style;
60 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
61 import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
62 import org.bouncycastle.asn1.x509.CRLDistPoint;
63 import org.bouncycastle.asn1.x509.CRLReason;
64 import org.bouncycastle.asn1.x509.DistributionPoint;
65 import org.bouncycastle.asn1.x509.DistributionPointName;
66 import org.bouncycastle.asn1.x509.Extension;
67 import org.bouncycastle.asn1.x509.GeneralName;
68 import org.bouncycastle.asn1.x509.GeneralNames;
69 import org.bouncycastle.asn1.x509.PolicyInformation;
70 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
71 import org.bouncycastle.jcajce.PKIXCRLStore;
72 import org.bouncycastle.jcajce.PKIXCRLStoreSelector;
73 import org.bouncycastle.jcajce.PKIXCertRevocationCheckerParameters;
74 import org.bouncycastle.jcajce.PKIXCertStore;
75 import org.bouncycastle.jcajce.PKIXCertStoreSelector;
76 import org.bouncycastle.jcajce.PKIXExtendedBuilderParameters;
77 import org.bouncycastle.jcajce.PKIXExtendedParameters;
78 import org.bouncycastle.jcajce.util.JcaJceHelper;
79 import org.bouncycastle.jce.exception.ExtCertPathBuilderException;
80 import org.bouncycastle.jce.exception.ExtCertPathValidatorException;
81 import org.bouncycastle.util.Properties;
82 import org.bouncycastle.util.Selector;
83 import org.bouncycastle.util.Store;
84 import org.bouncycastle.util.StoreException;
85 import org.bouncycastle.x509.X509AttributeCertificate;
86 
87 class CertPathValidatorUtilities
88 {
89     protected static final String CERTIFICATE_POLICIES = Extension.certificatePolicies.getId();
90     protected static final String BASIC_CONSTRAINTS = Extension.basicConstraints.getId();
91     protected static final String POLICY_MAPPINGS = Extension.policyMappings.getId();
92     protected static final String SUBJECT_ALTERNATIVE_NAME = Extension.subjectAlternativeName.getId();
93     protected static final String NAME_CONSTRAINTS = Extension.nameConstraints.getId();
94     protected static final String KEY_USAGE = Extension.keyUsage.getId();
95     protected static final String INHIBIT_ANY_POLICY = Extension.inhibitAnyPolicy.getId();
96     protected static final String ISSUING_DISTRIBUTION_POINT = Extension.issuingDistributionPoint.getId();
97     protected static final String DELTA_CRL_INDICATOR = Extension.deltaCRLIndicator.getId();
98     protected static final String POLICY_CONSTRAINTS = Extension.policyConstraints.getId();
99     protected static final String FRESHEST_CRL = Extension.freshestCRL.getId();
100     protected static final String CRL_DISTRIBUTION_POINTS = Extension.cRLDistributionPoints.getId();
101     protected static final String AUTHORITY_KEY_IDENTIFIER = Extension.authorityKeyIdentifier.getId();
102 
103     protected static final String ANY_POLICY = "2.5.29.32.0";
104 
105     protected static final String CRL_NUMBER = Extension.cRLNumber.getId();
106 
107     /*
108     * key usage bits
109     */
110     protected static final int KEY_CERT_SIGN = 5;
111     protected static final int CRL_SIGN = 6;
112 
113     protected static final String[] crlReasons = new String[]{
114         "unspecified",
115         "keyCompromise",
116         "cACompromise",
117         "affiliationChanged",
118         "superseded",
119         "cessationOfOperation",
120         "certificateHold",
121         "unknown",
122         "removeFromCRL",
123         "privilegeWithdrawn",
124         "aACompromise"};
125 
findTargets(PKIXExtendedBuilderParameters paramsPKIX)126     static Collection findTargets(PKIXExtendedBuilderParameters paramsPKIX) throws CertPathBuilderException
127     {
128         PKIXExtendedParameters baseParams = paramsPKIX.getBaseParameters();
129         PKIXCertStoreSelector certSelect = baseParams.getTargetConstraints();
130         HashSet targets = new HashSet();
131 
132         try
133         {
134             CertPathValidatorUtilities.findCertificates(targets, certSelect, baseParams.getCertificateStores());
135             CertPathValidatorUtilities.findCertificates(targets, certSelect, baseParams.getCertStores());
136         }
137         catch (AnnotatedException e)
138         {
139             throw new ExtCertPathBuilderException("Error finding target certificate.", e);
140         }
141 
142         if (!targets.isEmpty())
143         {
144             return targets;
145         }
146 
147         Certificate target = certSelect.getCertificate();
148         if (null == target)
149         {
150             throw new CertPathBuilderException("No certificate found matching targetConstraints.");
151         }
152 
153         return Collections.singleton(target);
154     }
155 
156     /**
157      * Search the given Set of TrustAnchor's for one that is the
158      * issuer of the given X509 certificate. Uses the default provider
159      * for signature verification.
160      *
161      * @param cert         the X509 certificate
162      * @param trustAnchors a Set of TrustAnchor's
163      * @return the <code>TrustAnchor</code> object if found or
164      *         <code>null</code> if not.
165      * @throws AnnotatedException if a TrustAnchor was found but the signature verification
166      * on the given certificate has thrown an exception.
167      */
findTrustAnchor( X509Certificate cert, Set trustAnchors)168     protected static TrustAnchor findTrustAnchor(
169         X509Certificate cert,
170         Set trustAnchors)
171         throws AnnotatedException
172     {
173         return findTrustAnchor(cert, trustAnchors, null);
174     }
175 
176     /**
177      * Search the given Set of TrustAnchor's for one that is the
178      * issuer of the given X509 certificate. Uses the specified
179      * provider for signature verification, or the default provider
180      * if null.
181      *
182      * @param cert         the X509 certificate
183      * @param trustAnchors a Set of TrustAnchor's
184      * @param sigProvider  the provider to use for signature verification
185      * @return the <code>TrustAnchor</code> object if found or
186      *         <code>null</code> if not.
187      * @throws AnnotatedException if a TrustAnchor was found but the signature verification
188      * on the given certificate has thrown an exception.
189      */
findTrustAnchor( X509Certificate cert, Set trustAnchors, String sigProvider)190     protected static TrustAnchor findTrustAnchor(
191         X509Certificate cert,
192         Set trustAnchors,
193         String sigProvider)
194         throws AnnotatedException
195     {
196         TrustAnchor trust = null;
197         PublicKey trustPublicKey = null;
198         Exception invalidKeyEx = null;
199 
200         X509CertSelector certSelectX509 = new X509CertSelector();
201         X509Principal certIssuerPrincipal;
202 	try
203         {
204 
205             certIssuerPrincipal = PrincipalUtil.getIssuerX509Principal(cert);
206         }
207         catch (Exception e)
208         {
209             throw new AnnotatedException(e.getMessage(), e);
210         }
211         try
212         {
213             certSelectX509.setSubject(certIssuerPrincipal.getEncoded());
214         }
215         catch (Exception e)
216         {
217             throw new AnnotatedException(e.getMessage(), e);
218         }
219 
220         X500Name certIssuerName = null;
221 
222         Iterator iter = trustAnchors.iterator();
223         while (iter.hasNext() && trust == null)
224         {
225             trust = (TrustAnchor)iter.next();
226             if (trust.getTrustedCert() != null)
227             {
228                 if (certSelectX509.match(trust.getTrustedCert()))
229                 {
230                     trustPublicKey = trust.getTrustedCert().getPublicKey();
231                 }
232                 else
233                 {
234                     trust = null;
235                 }
236             }
237             else if (trust.getCAName() != null
238                 && trust.getCAPublicKey() != null)
239             {
240                 if (certIssuerName == null)
241                 {
242                     certIssuerName = X500Name.getInstance(certIssuerPrincipal.getEncoded());
243                 }
244 
245                 try
246                 {
247                     X500Name caName = X500Name.getInstance(new X509Principal(trust.getCAName()).getEncoded());
248 
249                     if (certIssuerName.equals(caName))
250                     {
251                         trustPublicKey = trust.getCAPublicKey();
252                     }
253                     else
254                     {
255                         trust = null;
256                     }
257                 }
258                 catch (IllegalArgumentException ex)
259                 {
260                     trust = null;
261                 }
262             }
263             else
264             {
265                 trust = null;
266             }
267 
268             if (trustPublicKey != null)
269             {
270                 try
271                 {
272                     verifyX509Certificate(cert, trustPublicKey, sigProvider);
273                 }
274                 catch (Exception ex)
275                 {
276                     invalidKeyEx = ex;
277                     trust = null;
278                     trustPublicKey = null;
279                 }
280             }
281         }
282 
283         if (trust == null && invalidKeyEx != null)
284         {
285             throw new AnnotatedException("TrustAnchor found but certificate validation failed.", invalidKeyEx);
286         }
287 
288         return trust;
289     }
290 
isIssuerTrustAnchor( X509Certificate cert, Set trustAnchors, String sigProvider)291     static boolean isIssuerTrustAnchor(
292         X509Certificate cert,
293         Set trustAnchors,
294         String sigProvider)
295         throws AnnotatedException
296     {
297         try
298         {
299             return findTrustAnchor(cert, trustAnchors, sigProvider) != null;
300         }
301         catch (Exception e)
302         {
303             return false;
304         }
305     }
306 
getAdditionalStoresFromAltNames( byte[] issuerAlternativeName, Map<GeneralName, PKIXCertStore> altNameCertStoreMap)307     static List<PKIXCertStore> getAdditionalStoresFromAltNames(
308         byte[] issuerAlternativeName,
309         Map<GeneralName, PKIXCertStore> altNameCertStoreMap)
310         throws CertificateParsingException
311     {
312         // if in the IssuerAltName extension an URL
313         // is given, add an additional X.509 store
314         if (issuerAlternativeName == null)
315         {
316             return Collections.EMPTY_LIST;
317         }
318 
319         GeneralNames issuerAltName = GeneralNames.getInstance(ASN1OctetString.getInstance(issuerAlternativeName).getOctets());
320 
321         GeneralName[] names = issuerAltName.getNames();
322         List  stores = new ArrayList();
323 
324         for (int i = 0; i != names.length; i++)
325         {
326             GeneralName altName = names[i];
327 
328             PKIXCertStore altStore = (PKIXCertStore)altNameCertStoreMap.get(altName);
329             if (altStore != null)
330             {
331                 stores.add(altStore);
332             }
333         }
334 
335         return stores;
336     }
337 
getValidityDate(PKIXExtendedParameters paramsPKIX, Date currentDate)338     protected static Date getValidityDate(PKIXExtendedParameters paramsPKIX, Date currentDate)
339     {
340         Date validityDate = paramsPKIX.getValidityDate();
341 
342         return null == validityDate ? currentDate : validityDate;
343     }
344 
isSelfIssued(X509Certificate cert)345     protected static boolean isSelfIssued(X509Certificate cert)
346     {
347         return cert.getSubjectDN().equals(cert.getIssuerDN());
348     }
349 
350     /**
351      * Extract the value of the given extension, if it exists.
352      *
353      * @param ext The extension object.
354      * @param oid The object identifier to obtain.
355      * @throws AnnotatedException if the extension cannot be read.
356      */
getExtensionValue(java.security.cert.X509Extension ext, String oid)357     protected static ASN1Primitive getExtensionValue(java.security.cert.X509Extension ext, String oid)
358         throws AnnotatedException
359     {
360         byte[] bytes = ext.getExtensionValue(oid);
361 
362         return null == bytes ? null : getObject(oid, bytes);
363     }
364 
getObject(String oid, byte[] ext)365     private static ASN1Primitive getObject(String oid, byte[] ext) throws AnnotatedException
366     {
367         try
368         {
369             ASN1OctetString octs = ASN1OctetString.getInstance(ext);
370 
371             return ASN1Primitive.fromByteArray(octs.getOctets());
372         }
373         catch (Exception e)
374         {
375             throw new AnnotatedException("exception processing extension " + oid, e);
376         }
377     }
378 
getAlgorithmIdentifier(PublicKey key)379     protected static AlgorithmIdentifier getAlgorithmIdentifier(PublicKey key) throws CertPathValidatorException
380     {
381         try
382         {
383             return SubjectPublicKeyInfo.getInstance(key.getEncoded()).getAlgorithm();
384         }
385         catch (Exception e)
386         {
387             throw new ExtCertPathValidatorException("Subject public key cannot be decoded.", e);
388         }
389     }
390 
391     // crl checking
392 
393 
394     //
395     // policy checking
396     //
397 
getQualifierSet(ASN1Sequence qualifiers)398     protected static final Set getQualifierSet(ASN1Sequence qualifiers)
399         throws CertPathValidatorException
400     {
401         Set pq = new HashSet();
402 
403         if (qualifiers == null)
404         {
405             return pq;
406         }
407 
408         ByteArrayOutputStream bOut = new ByteArrayOutputStream();
409         ASN1OutputStream aOut = ASN1OutputStream.create(bOut);
410 
411         Enumeration e = qualifiers.getObjects();
412         while (e.hasMoreElements())
413         {
414             try
415             {
416                 aOut.writeObject((ASN1Encodable)e.nextElement());
417 
418                 pq.add(new PolicyQualifierInfo(bOut.toByteArray()));
419             }
420             catch (IOException ex)
421             {
422                 throw new ExtCertPathValidatorException("Policy qualifier info cannot be decoded.", ex);
423             }
424 
425             bOut.reset();
426         }
427 
428         return pq;
429     }
430 
removePolicyNode( PKIXPolicyNode validPolicyTree, List[] policyNodes, PKIXPolicyNode _node)431     protected static PKIXPolicyNode removePolicyNode(
432         PKIXPolicyNode validPolicyTree,
433         List[] policyNodes,
434         PKIXPolicyNode _node)
435     {
436         PKIXPolicyNode _parent = (PKIXPolicyNode)_node.getParent();
437 
438         if (validPolicyTree == null)
439         {
440             return null;
441         }
442 
443         if (_parent == null)
444         {
445             for (int j = 0; j < policyNodes.length; j++)
446             {
447                 policyNodes[j] = new ArrayList();
448             }
449 
450             return null;
451         }
452         else
453         {
454             _parent.removeChild(_node);
455             removePolicyNodeRecurse(policyNodes, _node);
456 
457             return validPolicyTree;
458         }
459     }
460 
removePolicyNodeRecurse( List[] policyNodes, PKIXPolicyNode _node)461     private static void removePolicyNodeRecurse(
462         List[] policyNodes,
463         PKIXPolicyNode _node)
464     {
465         policyNodes[_node.getDepth()].remove(_node);
466 
467         if (_node.hasChildren())
468         {
469             Iterator _iter = _node.getChildren();
470             while (_iter.hasNext())
471             {
472                 PKIXPolicyNode _child = (PKIXPolicyNode)_iter.next();
473                 removePolicyNodeRecurse(policyNodes, _child);
474             }
475         }
476     }
477 
478 
processCertD1i( int index, List[] policyNodes, ASN1ObjectIdentifier pOid, Set pq)479     protected static boolean processCertD1i(
480         int index,
481         List[] policyNodes,
482         ASN1ObjectIdentifier pOid,
483         Set pq)
484     {
485         List policyNodeVec = policyNodes[index - 1];
486 
487         for (int j = 0; j < policyNodeVec.size(); j++)
488         {
489             PKIXPolicyNode node = (PKIXPolicyNode)policyNodeVec.get(j);
490             Set expectedPolicies = node.getExpectedPolicies();
491 
492             if (expectedPolicies.contains(pOid.getId()))
493             {
494                 Set childExpectedPolicies = new HashSet();
495                 childExpectedPolicies.add(pOid.getId());
496 
497                 PKIXPolicyNode child = new PKIXPolicyNode(new ArrayList(),
498                     index,
499                     childExpectedPolicies,
500                     node,
501                     pq,
502                     pOid.getId(),
503                     false);
504                 node.addChild(child);
505                 policyNodes[index].add(child);
506 
507                 return true;
508             }
509         }
510 
511         return false;
512     }
513 
processCertD1ii( int index, List[] policyNodes, ASN1ObjectIdentifier _poid, Set _pq)514     protected static void processCertD1ii(
515         int index,
516         List[] policyNodes,
517         ASN1ObjectIdentifier _poid,
518         Set _pq)
519     {
520         List policyNodeVec = policyNodes[index - 1];
521 
522         for (int j = 0; j < policyNodeVec.size(); j++)
523         {
524             PKIXPolicyNode _node = (PKIXPolicyNode)policyNodeVec.get(j);
525 
526             if (ANY_POLICY.equals(_node.getValidPolicy()))
527             {
528                 Set _childExpectedPolicies = new HashSet();
529                 _childExpectedPolicies.add(_poid.getId());
530 
531                 PKIXPolicyNode _child = new PKIXPolicyNode(new ArrayList(),
532                     index,
533                     _childExpectedPolicies,
534                     _node,
535                     _pq,
536                     _poid.getId(),
537                     false);
538                 _node.addChild(_child);
539                 policyNodes[index].add(_child);
540                 return;
541             }
542         }
543     }
544 
prepareNextCertB1( int i, List[] policyNodes, String id_p, Map m_idp, X509Certificate cert )545     protected static void prepareNextCertB1(
546         int i,
547         List[] policyNodes,
548         String id_p,
549         Map m_idp,
550         X509Certificate cert
551     )
552         throws AnnotatedException, CertPathValidatorException
553     {
554         boolean idp_found = false;
555         Iterator nodes_i = policyNodes[i].iterator();
556         while (nodes_i.hasNext())
557         {
558             PKIXPolicyNode node = (PKIXPolicyNode)nodes_i.next();
559             if (node.getValidPolicy().equals(id_p))
560             {
561                 idp_found = true;
562                 node.expectedPolicies = (Set)m_idp.get(id_p);
563                 break;
564             }
565         }
566 
567         if (!idp_found)
568         {
569             nodes_i = policyNodes[i].iterator();
570             while (nodes_i.hasNext())
571             {
572                 PKIXPolicyNode node = (PKIXPolicyNode)nodes_i.next();
573                 if (ANY_POLICY.equals(node.getValidPolicy()))
574                 {
575                     Set pq = null;
576                     ASN1Sequence policies = null;
577                     try
578                     {
579                         policies = DERSequence.getInstance(getExtensionValue(cert, CERTIFICATE_POLICIES));
580                     }
581                     catch (Exception e)
582                     {
583                         throw new AnnotatedException("Certificate policies cannot be decoded.", e);
584                     }
585                     Enumeration e = policies.getObjects();
586                     while (e.hasMoreElements())
587                     {
588                         PolicyInformation pinfo = null;
589 
590                         try
591                         {
592                             pinfo = PolicyInformation.getInstance(e.nextElement());
593                         }
594                         catch (Exception ex)
595                         {
596                             throw new AnnotatedException("Policy information cannot be decoded.", ex);
597                         }
598                         if (ANY_POLICY.equals(pinfo.getPolicyIdentifier().getId()))
599                         {
600                             try
601                             {
602                                 pq = getQualifierSet(pinfo.getPolicyQualifiers());
603                             }
604                             catch (CertPathValidatorException ex)
605                             {
606                                 throw new ExtCertPathValidatorException(
607                                     "Policy qualifier info set could not be built.", ex);
608                             }
609                             break;
610                         }
611                     }
612                     boolean ci = false;
613                     if (cert.getCriticalExtensionOIDs() != null)
614                     {
615                         ci = cert.getCriticalExtensionOIDs().contains(CERTIFICATE_POLICIES);
616                     }
617 
618                     PKIXPolicyNode p_node = (PKIXPolicyNode)node.getParent();
619                     if (ANY_POLICY.equals(p_node.getValidPolicy()))
620                     {
621                         PKIXPolicyNode c_node = new PKIXPolicyNode(
622                             new ArrayList(), i,
623                             (Set)m_idp.get(id_p),
624                             p_node, pq, id_p, ci);
625                         p_node.addChild(c_node);
626                         policyNodes[i].add(c_node);
627                     }
628                     break;
629                 }
630             }
631         }
632     }
633 
prepareNextCertB2( int i, List[] policyNodes, String id_p, PKIXPolicyNode validPolicyTree)634     protected static PKIXPolicyNode prepareNextCertB2(
635         int i,
636         List[] policyNodes,
637         String id_p,
638         PKIXPolicyNode validPolicyTree)
639     {
640         Iterator nodes_i = policyNodes[i].iterator();
641         while (nodes_i.hasNext())
642         {
643             PKIXPolicyNode node = (PKIXPolicyNode)nodes_i.next();
644             if (node.getValidPolicy().equals(id_p))
645             {
646                 PKIXPolicyNode p_node = (PKIXPolicyNode)node.getParent();
647                 p_node.removeChild(node);
648                 nodes_i.remove();
649                 for (int k = (i - 1); k >= 0; k--)
650                 {
651                     List nodes = policyNodes[k];
652                     for (int l = 0; l < nodes.size(); l++)
653                     {
654                         PKIXPolicyNode node2 = (PKIXPolicyNode)nodes.get(l);
655                         if (!node2.hasChildren())
656                         {
657                             validPolicyTree = removePolicyNode(validPolicyTree, policyNodes, node2);
658                             if (validPolicyTree == null)
659                             {
660                                 break;
661                             }
662                         }
663                     }
664                 }
665             }
666         }
667         return validPolicyTree;
668     }
669 
isAnyPolicy( Set policySet)670     protected static boolean isAnyPolicy(
671         Set policySet)
672     {
673         return policySet == null || policySet.contains(ANY_POLICY) || policySet.isEmpty();
674     }
675 
676     /**
677      * Return a Collection of all certificates or attribute certificates found in the X509Store's
678      * that are matching the certSelect criteriums.
679      *
680      * @param certs
681      *            a {@link HashSet} to which the certificates will be added.
682      * @param certSelect
683      *            a {@link Selector} object that will be used to select the certificates
684      * @param certStores
685      *            a List containing only {@link Store} objects. These are used to search for
686      *            certificates.
687      * @return a Collection of all found {@link X509Certificate} May be empty but never
688      *         <code>null</code>.
689      */
findCertificates(HashSet certs, PKIXCertStoreSelector certSelect, List certStores)690     protected static void findCertificates(HashSet certs, PKIXCertStoreSelector certSelect, List certStores)
691         throws AnnotatedException
692     {
693         Iterator iter = certStores.iterator();
694         while (iter.hasNext())
695         {
696             Object obj = iter.next();
697             if (obj instanceof Store)
698             {
699                 Store certStore = (Store)obj;
700                 try
701                 {
702                     certs.addAll(certStore.getMatches(certSelect));
703                 }
704                 catch (StoreException e)
705                 {
706                     throw new AnnotatedException("Problem while picking certificates from X.509 store.", e);
707                 }
708             }
709             else
710             {
711                 CertStore certStore = (CertStore)obj;
712                 try
713                 {
714                     certs.addAll(PKIXCertStoreSelector.getCertificates(certSelect, certStore));
715                 }
716                 catch (CertStoreException e)
717                 {
718                     throw new AnnotatedException("Problem while picking certificates from certificate store.", e);
719                 }
720             }
721         }
722     }
723 
getAdditionalStoresFromCRLDistributionPoint( CRLDistPoint crldp, Map<GeneralName, PKIXCRLStore> namedCRLStoreMap, Date validDate, JcaJceHelper helper)724     static List<PKIXCRLStore> getAdditionalStoresFromCRLDistributionPoint(
725         CRLDistPoint crldp, Map<GeneralName, PKIXCRLStore> namedCRLStoreMap, Date validDate, JcaJceHelper helper)
726         throws AnnotatedException
727     {
728         if (null == crldp)
729         {
730             return Collections.EMPTY_LIST;
731         }
732 
733         DistributionPoint dps[];
734         try
735         {
736             dps = crldp.getDistributionPoints();
737         }
738         catch (Exception e)
739         {
740             throw new AnnotatedException("Distribution points could not be read.", e);
741         }
742 
743         List stores = new ArrayList();
744 
745         for (int i = 0; i < dps.length; i++)
746         {
747             DistributionPointName dpn = dps[i].getDistributionPoint();
748             // look for URLs in fullName
749             if (dpn != null && dpn.getType() == DistributionPointName.FULL_NAME)
750             {
751                 GeneralName[] genNames = GeneralNames.getInstance(dpn.getName()).getNames();
752 
753                 for (int j = 0; j < genNames.length; j++)
754                 {
755                     PKIXCRLStore store = (PKIXCRLStore)namedCRLStoreMap.get(genNames[j]);
756                     if (store != null)
757                     {
758                         stores.add(store);
759                     }
760                 }
761             }
762         }
763 
764         // if the named CRL store is empty, and we're told to check with CRLDP
765         if (stores.isEmpty() && Properties.isOverrideSet("org.bouncycastle.x509.enableCRLDP"))
766         {
767             CertificateFactory certFact;
768             try
769             {
770                 certFact = helper.createCertificateFactory("X.509");
771             }
772             catch (Exception e)
773             {
774                 throw new AnnotatedException("cannot create certificate factory: " + e.getMessage(), e);
775             }
776 
777             for (int i = 0; i < dps.length; i++)
778             {
779                 DistributionPointName dpn = dps[i].getDistributionPoint();
780                 // look for URLs in fullName
781                 if (dpn != null && dpn.getType() == DistributionPointName.FULL_NAME)
782                 {
783                     GeneralName[] genNames = GeneralNames.getInstance(dpn.getName()).getNames();
784 
785                     for (int j = 0; j < genNames.length; j++)
786                     {
787                         GeneralName name = genNames[i];
788                         if (name.getTagNo() == GeneralName.uniformResourceIdentifier)
789                         {
790                             try
791                             {
792                                 URL distributionPoint = new URL(((ASN1String)name.getName()).getString());
793                                 PKIXCRLStore store = CrlCache.getCrl(certFact, validDate, distributionPoint);
794                                 if (store != null)
795                                 {
796                                     stores.add(store);
797                                 }
798                                 break;
799                             }
800                             catch (Exception e)
801                             {
802                                 // ignore...  TODO: maybe log
803                             }
804                         }
805                     }
806                 }
807             }
808         }
809 
810         return stores;
811     }
812 
813     /**
814      * Add the CRL issuers from the cRLIssuer field of the distribution point or
815      * from the certificate if not given to the issuer criterion of the
816      * <code>selector</code>.
817      * <p>
818      * The <code>issuerPrincipals</code> are a collection with a single
819      * <code>X500Name</code> for <code>X509Certificate</code>s.
820      * </p>
821      * @param dp               The distribution point.
822      * @param issuerPrincipals The issuers of the certificate or attribute
823      *                         certificate which contains the distribution point.
824      * @param selector         The CRL selector.
825      * @throws AnnotatedException if an exception occurs while processing.
826      * @throws ClassCastException if <code>issuerPrincipals</code> does not
827      * contain only <code>X500Name</code>s.
828      */
getCRLIssuersFromDistributionPoint( DistributionPoint dp, Collection issuerPrincipals, X509CRLSelector selector)829     protected static void getCRLIssuersFromDistributionPoint(
830         DistributionPoint dp,
831         Collection issuerPrincipals,
832         X509CRLSelector selector)
833         throws AnnotatedException
834     {
835         List issuers = new ArrayList();
836         // indirect CRL
837         if (dp.getCRLIssuer() != null)
838         {
839             GeneralName genNames[] = dp.getCRLIssuer().getNames();
840             // look for a DN
841             for (int j = 0; j < genNames.length; j++)
842             {
843                 if (genNames[j].getTagNo() == GeneralName.directoryName)
844                 {
845                     try
846                     {
847                         issuers.add(X500Name.getInstance(genNames[j].getName().toASN1Primitive().getEncoded()));
848                     }
849                     catch (IOException e)
850                     {
851                         throw new AnnotatedException(
852                             "CRL issuer information from distribution point cannot be decoded.", e);
853                     }
854                 }
855             }
856         }
857         else
858         {
859             /*
860              * certificate issuer is CRL issuer, distributionPoint field MUST be
861              * present.
862              */
863             if (dp.getDistributionPoint() == null)
864             {
865                 throw new AnnotatedException(
866                     "CRL issuer is omitted from distribution point but no distributionPoint field present.");
867             }
868             // add and check issuer principals
869             for (Iterator it = issuerPrincipals.iterator(); it.hasNext(); )
870             {
871                 issuers.add(it.next());
872             }
873         }
874         // TODO: is not found although this should correctly add the rel name. selector of Sun is buggy here or PKI test case is invalid
875         // distributionPoint
876 //        if (dp.getDistributionPoint() != null)
877 //        {
878 //            // look for nameRelativeToCRLIssuer
879 //            if (dp.getDistributionPoint().getType() == DistributionPointName.NAME_RELATIVE_TO_CRL_ISSUER)
880 //            {
881 //                // append fragment to issuer, only one
882 //                // issuer can be there, if this is given
883 //                if (issuers.size() != 1)
884 //                {
885 //                    throw new AnnotatedException(
886 //                        "nameRelativeToCRLIssuer field is given but more than one CRL issuer is given.");
887 //                }
888 //                ASN1Encodable relName = dp.getDistributionPoint().getName();
889 //                Iterator it = issuers.iterator();
890 //                List issuersTemp = new ArrayList(issuers.size());
891 //                while (it.hasNext())
892 //                {
893 //                    Enumeration e = null;
894 //                    try
895 //                    {
896 //                        e = ASN1Sequence.getInstance(
897 //                            new ASN1InputStream(((X509Principal) it.next())
898 //                                .getEncoded()).readObject()).getObjects();
899 //                    }
900 //                    catch (IOException ex)
901 //                    {
902 //                        throw new AnnotatedException(
903 //                            "Cannot decode CRL issuer information.", ex);
904 //                    }
905 //                    ASN1EncodableVector v = new ASN1EncodableVector();
906 //                    while (e.hasMoreElements())
907 //                    {
908 //                        v.add((ASN1Encodable) e.nextElement());
909 //                    }
910 //                    v.add(relName);
911 //                    issuersTemp.add(new X509Principal(new DERSequence(v)
912 //                        .getDEREncoded()));
913 //                }
914 //                issuers.clear();
915 //                issuers.addAll(issuersTemp);
916 //            }
917 //        }
918         Iterator it = issuers.iterator();
919         while (it.hasNext())
920         {
921             try
922             {
923                 selector.addIssuerName(((X500Name)it.next()).getEncoded());
924             }
925             catch (IOException ex)
926             {
927                 throw new AnnotatedException(
928                     "Cannot decode CRL issuer information.", ex);
929             }
930         }
931     }
932 
getSerialNumber(Object cert)933     private static BigInteger getSerialNumber(Object cert)
934     {
935         return ((X509Certificate)cert).getSerialNumber();
936     }
937 
getCertStatus( Date validDate, X509CRL crl, Object cert, CertStatus certStatus)938     protected static void getCertStatus(
939         Date validDate,
940         X509CRL crl,
941         Object cert,
942         CertStatus certStatus)
943         throws AnnotatedException
944     {
945         boolean isIndirect;
946         try
947         {
948             isIndirect = X509CRLObject.isIndirectCRL(crl);
949         }
950         catch (CRLException exception)
951         {
952             throw new AnnotatedException("Failed check for indirect CRL.", exception);
953         }
954 
955         X509CRLEntry crl_entry;
956         if (isIndirect)
957         {
958             crl_entry = crl.getRevokedCertificate(getSerialNumber(cert));
959 
960             if (crl_entry == null)
961             {
962                 return;
963             }
964 
965             X509Principal certificateIssuer = ((X509CRLEntryObject)crl_entry).getCertificateIssuer();
966 
967             X500Name certIssuer;
968             if (certificateIssuer == null)
969             {
970                 certIssuer = PrincipalUtils.getIssuerPrincipal(crl);
971             }
972             else
973             {
974 		try
975                 {
976                 certIssuer = X500Name.getInstance(certificateIssuer.getEncoded());
977                 }
978                 catch (Exception e)
979 		{
980                     throw new AnnotatedException(e.toString(), e);
981 		}
982             }
983 
984             if (!PrincipalUtils.getEncodedIssuerPrincipal(cert).equals(certIssuer))
985             {
986                 return;
987             }
988         }
989         else if (!PrincipalUtils.getEncodedIssuerPrincipal(cert).equals(PrincipalUtils.getIssuerPrincipal(crl)))
990         {
991             return;  // not for our issuer, ignore
992         }
993         else
994         {
995             crl_entry = crl.getRevokedCertificate(getSerialNumber(cert));
996 
997             if (crl_entry == null)
998             {
999                 return;
1000             }
1001         }
1002 
1003         ASN1Enumerated reasonCode = null;
1004         if (crl_entry.hasExtensions())
1005         {
1006             if (crl_entry.hasUnsupportedCriticalExtension())
1007             {
1008                 throw new AnnotatedException("CRL entry has unsupported critical extensions.");
1009             }
1010 
1011             try
1012             {
1013                 reasonCode = ASN1Enumerated
1014                     .getInstance(CertPathValidatorUtilities.getExtensionValue(crl_entry, Extension.reasonCode.getId()));
1015             }
1016             catch (Exception e)
1017             {
1018                 throw new AnnotatedException("Reason code CRL entry extension could not be decoded.", e);
1019             }
1020         }
1021 
1022         int reasonCodeValue = (null == reasonCode)
1023             ?   CRLReason.unspecified
1024             :   reasonCode.intValueExact();
1025 
1026         // for reason keyCompromise, caCompromise, aACompromise or unspecified
1027         if (!(validDate.getTime() < crl_entry.getRevocationDate().getTime())
1028             || reasonCodeValue == CRLReason.unspecified
1029             || reasonCodeValue == CRLReason.keyCompromise
1030             || reasonCodeValue == CRLReason.cACompromise
1031             || reasonCodeValue == CRLReason.aACompromise)
1032         {
1033             // (i) or (j)
1034             certStatus.setCertStatus(reasonCodeValue);
1035             certStatus.setRevocationDate(crl_entry.getRevocationDate());
1036         }
1037     }
1038 
1039     /**
1040      * Fetches delta CRLs according to RFC 3280 section 5.2.4.
1041      *
1042      * @param validityDate The date for which the delta CRLs must be valid.
1043      * @param completeCRL The complete CRL the delta CRL is for.
1044      * @return A <code>Set</code> of <code>X509CRL</code>s with delta CRLs.
1045      * @throws AnnotatedException if an exception occurs while picking the delta
1046      * CRLs.
1047      */
getDeltaCRLs(Date validityDate, X509CRL completeCRL, List<CertStore> certStores, List<PKIXCRLStore> pkixCrlStores, JcaJceHelper helper)1048     protected static Set getDeltaCRLs(Date validityDate,
1049                                       X509CRL completeCRL,
1050                                       List<CertStore> certStores,
1051                                       List<PKIXCRLStore> pkixCrlStores,
1052                                       JcaJceHelper helper)
1053         throws AnnotatedException
1054     {
1055         X509CRLSelector baseDeltaSelect = new X509CRLSelector();
1056         // 5.2.4 (a)
1057         try
1058         {
1059             baseDeltaSelect.addIssuerName(PrincipalUtils.getIssuerPrincipal(completeCRL).getEncoded());
1060         }
1061         catch (IOException e)
1062         {
1063             throw new AnnotatedException("Cannot extract issuer from CRL.", e);
1064         }
1065 
1066         BigInteger completeCRLNumber = null;
1067         try
1068         {
1069             ASN1Primitive derObject = CertPathValidatorUtilities.getExtensionValue(completeCRL, CRL_NUMBER);
1070             if (derObject != null)
1071             {
1072                 completeCRLNumber = ASN1Integer.getInstance(derObject).getPositiveValue();
1073             }
1074         }
1075         catch (Exception e)
1076         {
1077             throw new AnnotatedException(
1078                 "CRL number extension could not be extracted from CRL.", e);
1079         }
1080 
1081         // 5.2.4 (b)
1082         byte[] idp;
1083         try
1084         {
1085             idp = completeCRL.getExtensionValue(ISSUING_DISTRIBUTION_POINT);
1086         }
1087         catch (Exception e)
1088         {
1089             throw new AnnotatedException("Issuing distribution point extension value could not be read.", e);
1090         }
1091 
1092         // 5.2.4 (d)
1093 
1094         baseDeltaSelect.setMinCRLNumber(completeCRLNumber == null ? null : completeCRLNumber.add(BigInteger.valueOf(1)));
1095 
1096         PKIXCRLStoreSelector.Builder selBuilder = new PKIXCRLStoreSelector.Builder(baseDeltaSelect);
1097 
1098         selBuilder.setIssuingDistributionPoint(idp);
1099         selBuilder.setIssuingDistributionPointEnabled(true);
1100 
1101         // 5.2.4 (c)
1102         selBuilder.setMaxBaseCRLNumber(completeCRLNumber);
1103 
1104         PKIXCRLStoreSelector deltaSelect = selBuilder.build();
1105 
1106         // find delta CRLs
1107         Set temp = PKIXCRLUtil.findCRLs(deltaSelect, validityDate, certStores, pkixCrlStores);
1108 
1109         // if the named CRL store is empty, and we're told to check with CRLDP
1110         if (temp.isEmpty() && Properties.isOverrideSet("org.bouncycastle.x509.enableCRLDP"))
1111         {
1112             CertificateFactory certFact;
1113             try
1114             {
1115                 certFact = helper.createCertificateFactory("X.509");
1116             }
1117             catch (Exception e)
1118             {
1119                 throw new AnnotatedException("cannot create certificate factory: " + e.getMessage(), e);
1120             }
1121 
1122             CRLDistPoint id = CRLDistPoint.getInstance(idp);
1123             DistributionPoint[] dps = id.getDistributionPoints();
1124             for (int i = 0; i < dps.length; i++)
1125             {
1126                 DistributionPointName dpn = dps[i].getDistributionPoint();
1127                 // look for URLs in fullName
1128                 if (dpn != null && dpn.getType() == DistributionPointName.FULL_NAME)
1129                 {
1130                     GeneralName[] genNames = GeneralNames.getInstance(dpn.getName()).getNames();
1131 
1132                     for (int j = 0; j < genNames.length; j++)
1133                     {
1134                         GeneralName name = genNames[i];
1135                         if (name.getTagNo() == GeneralName.uniformResourceIdentifier)
1136                         {
1137                             try
1138                             {
1139                                 PKIXCRLStore store = CrlCache.getCrl(certFact, validityDate,
1140                                     new URL(((ASN1String)name.getName()).getString()));
1141                                 if (store != null)
1142                                 {
1143                                     ArrayList ls = new ArrayList();
1144                                     ls.add(store);
1145                                     temp = PKIXCRLUtil.findCRLs(deltaSelect, validityDate, Collections.EMPTY_LIST,
1146                                         ls);
1147                                 }
1148                                 break;
1149                             }
1150                             catch (Exception e)
1151                             {
1152                                 // ignore...  TODO: maybe log
1153                             }
1154                         }
1155                     }
1156                 }
1157             }
1158         }
1159 
1160         Set result = new HashSet();
1161 
1162         for (Iterator it = temp.iterator(); it.hasNext(); )
1163         {
1164             X509CRL crl = (X509CRL)it.next();
1165 
1166             if (isDeltaCRL(crl))
1167             {
1168                 result.add(crl);
1169             }
1170         }
1171 
1172         return result;
1173     }
1174 
isDeltaCRL(X509CRL crl)1175     private static boolean isDeltaCRL(X509CRL crl)
1176     {
1177         Set critical = crl.getCriticalExtensionOIDs();
1178 
1179         if (critical == null)
1180         {
1181             return false;
1182         }
1183 
1184         return critical.contains(RFC3280CertPathUtilities.DELTA_CRL_INDICATOR);
1185     }
1186 
1187     /**
1188      * Fetches complete CRLs according to RFC 3280.
1189      *
1190      * @param dp          The distribution point for which the complete CRL
1191      * @param cert        The <code>X509Certificate</code> for
1192      *                    which the CRL should be searched.
1193      * @param currentDate The date for which the delta CRLs must be valid.
1194      * @param paramsPKIX  The extended PKIX parameters.
1195      * @return A <code>Set</code> of <code>X509CRL</code>s with complete
1196      *         CRLs.
1197      * @throws AnnotatedException if an exception occurs while picking the CRLs
1198      * or no CRLs are found.
1199      */
getCompleteCRLs(PKIXCertRevocationCheckerParameters params, DistributionPoint dp, Object cert, PKIXExtendedParameters paramsPKIX, Date validityDate)1200     protected static Set getCompleteCRLs(PKIXCertRevocationCheckerParameters params, DistributionPoint dp, Object cert,
1201         PKIXExtendedParameters paramsPKIX, Date validityDate)
1202         throws AnnotatedException, RecoverableCertPathValidatorException
1203     {
1204         X509CRLSelector baseCrlSelect = new X509CRLSelector();
1205 
1206         try
1207         {
1208             Set issuers = new HashSet();
1209             issuers.add(PrincipalUtils.getEncodedIssuerPrincipal(cert));
1210 
1211             CertPathValidatorUtilities.getCRLIssuersFromDistributionPoint(dp, issuers, baseCrlSelect);
1212         }
1213         catch (AnnotatedException e)
1214         {
1215             throw new AnnotatedException("Could not get issuer information from distribution point.", e);
1216         }
1217 
1218         if (cert instanceof X509Certificate)
1219         {
1220             baseCrlSelect.setCertificateChecking((X509Certificate)cert);
1221         }
1222 
1223         PKIXCRLStoreSelector crlSelect = new PKIXCRLStoreSelector.Builder(baseCrlSelect).setCompleteCRLEnabled(true)
1224             .build();
1225 
1226         Set crls = PKIXCRLUtil.findCRLs(crlSelect, validityDate, paramsPKIX.getCertStores(), paramsPKIX.getCRLStores());
1227 
1228         checkCRLsNotEmpty(params, crls, cert);
1229 
1230         return crls;
1231     }
1232 
getValidCertDateFromValidityModel(Date validityDate, int validityModel, CertPath certPath, int index)1233     protected static Date getValidCertDateFromValidityModel(Date validityDate, int validityModel, CertPath certPath,
1234         int index) throws AnnotatedException
1235     {
1236         if (PKIXExtendedParameters.CHAIN_VALIDITY_MODEL != validityModel || index <= 0)
1237         {
1238             // use given signing/encryption/... time (or current date)
1239             return validityDate;
1240         }
1241 
1242         X509Certificate issuedCert = (X509Certificate)certPath.getCertificates().get(index - 1);
1243 
1244         if (index - 1 == 0)
1245         {
1246             // use time when cert was issued, if available
1247             ASN1GeneralizedTime dateOfCertgen = null;
1248             try
1249             {
1250                 byte[] extBytes = ((X509Certificate)certPath.getCertificates().get(index - 1))
1251                     .getExtensionValue(ISISMTTObjectIdentifiers.id_isismtt_at_dateOfCertGen.getId());
1252                 if (extBytes != null)
1253                 {
1254                     dateOfCertgen = ASN1GeneralizedTime.getInstance(ASN1Primitive.fromByteArray(extBytes));
1255                 }
1256             }
1257             catch (IOException e)
1258             {
1259                 throw new AnnotatedException("Date of cert gen extension could not be read.");
1260             }
1261             catch (IllegalArgumentException e)
1262             {
1263                 throw new AnnotatedException("Date of cert gen extension could not be read.");
1264             }
1265             if (dateOfCertgen != null)
1266             {
1267                 try
1268                 {
1269                     return dateOfCertgen.getDate();
1270                 }
1271                 catch (ParseException e)
1272                 {
1273                     throw new AnnotatedException("Date from date of cert gen extension could not be parsed.", e);
1274                 }
1275             }
1276         }
1277 
1278         return issuedCert.getNotBefore();
1279     }
1280 
1281     /**
1282      * Return the next working key inheriting DSA parameters if necessary.
1283      * <p>
1284      * This methods inherits DSA parameters from the indexed certificate or
1285      * previous certificates in the certificate chain to the returned
1286      * <code>PublicKey</code>. The list is searched upwards, meaning the end
1287      * certificate is at position 0 and previous certificates are following.
1288      * </p>
1289      * <p>
1290      * If the indexed certificate does not contain a DSA key this method simply
1291      * returns the public key. If the DSA key already contains DSA parameters
1292      * the key is also only returned.
1293      * </p>
1294      *
1295      * @param certs The certification path.
1296      * @param index The index of the certificate which contains the public key
1297      *              which should be extended with DSA parameters.
1298      * @return The public key of the certificate in list position
1299      *         <code>index</code> extended with DSA parameters if applicable.
1300      * @throws AnnotatedException if DSA parameters cannot be inherited.
1301      */
getNextWorkingKey(List certs, int index, JcaJceHelper helper)1302     protected static PublicKey getNextWorkingKey(List certs, int index, JcaJceHelper helper)
1303         throws CertPathValidatorException
1304     {
1305         Certificate cert = (Certificate)certs.get(index);
1306         PublicKey pubKey = cert.getPublicKey();
1307         if (!(pubKey instanceof DSAPublicKey))
1308         {
1309             return pubKey;
1310         }
1311         DSAPublicKey dsaPubKey = (DSAPublicKey)pubKey;
1312         if (dsaPubKey.getParams() != null)
1313         {
1314             return dsaPubKey;
1315         }
1316         for (int i = index + 1; i < certs.size(); i++)
1317         {
1318             X509Certificate parentCert = (X509Certificate)certs.get(i);
1319             pubKey = parentCert.getPublicKey();
1320             if (!(pubKey instanceof DSAPublicKey))
1321             {
1322                 throw new CertPathValidatorException(
1323                     "DSA parameters cannot be inherited from previous certificate.");
1324             }
1325             DSAPublicKey prevDSAPubKey = (DSAPublicKey)pubKey;
1326             if (prevDSAPubKey.getParams() == null)
1327             {
1328                 continue;
1329             }
1330             DSAParams dsaParams = prevDSAPubKey.getParams();
1331             DSAPublicKeySpec dsaPubKeySpec = new DSAPublicKeySpec(
1332                 dsaPubKey.getY(), dsaParams.getP(), dsaParams.getQ(), dsaParams.getG());
1333             try
1334             {
1335                 KeyFactory keyFactory = helper.createKeyFactory("DSA");
1336                 return keyFactory.generatePublic(dsaPubKeySpec);
1337             }
1338             catch (Exception exception)
1339             {
1340                 throw new RuntimeException(exception.getMessage());
1341             }
1342         }
1343         throw new CertPathValidatorException("DSA parameters cannot be inherited from previous certificate.");
1344     }
1345 
1346     /**
1347      * Find the issuer certificates of a given certificate.
1348      *
1349      * @param cert       The certificate for which an issuer should be found.
1350      * @return A <code>Collection</code> object containing the issuer
1351      *         <code>X509Certificate</code>s. Never <code>null</code>.
1352      * @throws AnnotatedException if an error occurs.
1353      */
findIssuerCerts( X509Certificate cert, List<CertStore> certStores, List<PKIXCertStore> pkixCertStores)1354     static Collection findIssuerCerts(
1355         X509Certificate cert,
1356         List<CertStore> certStores,
1357         List<PKIXCertStore> pkixCertStores)
1358         throws AnnotatedException
1359     {
1360         X509CertSelector selector = new X509CertSelector();
1361 
1362         try
1363         {
1364             selector.setSubject(PrincipalUtils.getIssuerPrincipal(cert).getEncoded());
1365         }
1366         catch (Exception e)
1367         {
1368             throw new AnnotatedException(
1369                 "Subject criteria for certificate selector to find issuer certificate could not be set.", e);
1370         }
1371 
1372         try
1373         {
1374             byte[] akiExtensionValue = cert.getExtensionValue(AUTHORITY_KEY_IDENTIFIER);
1375             if (akiExtensionValue != null)
1376             {
1377                 ASN1OctetString aki = ASN1OctetString.getInstance(akiExtensionValue);
1378                 byte[] authorityKeyIdentifier = AuthorityKeyIdentifier.getInstance(aki.getOctets()).getKeyIdentifier();
1379                 if (authorityKeyIdentifier != null)
1380                 {
1381                     selector.setSubjectKeyIdentifier(new DEROctetString(authorityKeyIdentifier).getEncoded());
1382                 }
1383             }
1384         }
1385         catch (Exception e)
1386         {
1387             // authority key identifier could not be retrieved from target cert, just search without it
1388         }
1389 
1390         PKIXCertStoreSelector certSelect = new PKIXCertStoreSelector.Builder(selector).build();
1391         HashSet certs = new HashSet();
1392 
1393         try
1394         {
1395             CertPathValidatorUtilities.findCertificates(certs, certSelect, certStores);
1396             CertPathValidatorUtilities.findCertificates(certs, certSelect, pkixCertStores);
1397         }
1398         catch (AnnotatedException e)
1399         {
1400             throw new AnnotatedException("Issuer certificate cannot be searched.", e);
1401         }
1402 
1403         // issuers cannot be verified because possible DSA inheritance parameters are missing
1404 
1405         return certs;
1406     }
1407 
verifyX509Certificate(X509Certificate cert, PublicKey publicKey, String sigProvider)1408     protected static void verifyX509Certificate(X509Certificate cert, PublicKey publicKey, String sigProvider)
1409         throws Exception
1410     {
1411         if (sigProvider == null)
1412         {
1413             cert.verify(publicKey);
1414         }
1415         else
1416         {
1417             cert.verify(publicKey, sigProvider);
1418         }
1419     }
1420 
checkCRLsNotEmpty(PKIXCertRevocationCheckerParameters params, Set crls, Object cert)1421     static void checkCRLsNotEmpty(PKIXCertRevocationCheckerParameters params, Set crls, Object cert)
1422         throws RecoverableCertPathValidatorException
1423     {
1424         if (crls.isEmpty())
1425         {
1426             if (cert instanceof X509AttributeCertificate)
1427             {
1428                 X509AttributeCertificate aCert = (X509AttributeCertificate)cert;
1429 
1430                 throw new RecoverableCertPathValidatorException("No CRLs found for issuer \"" + aCert.getIssuer().getPrincipals()[0] + "\"", null,
1431                                 params.getCertPath(), params.getIndex());
1432             }
1433             else
1434             {
1435                 X509Certificate xCert = (X509Certificate)cert;
1436 
1437                 throw new RecoverableCertPathValidatorException("No CRLs found for issuer \"" + RFC4519Style.INSTANCE.toString(PrincipalUtils.getIssuerPrincipal(xCert)) + "\"", null,
1438                     params.getCertPath(), params.getIndex());
1439             }
1440         }
1441     }
1442 }
1443