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