1 package org.bouncycastle.pkix.jcajce;
2 
3 import java.io.IOException;
4 import java.security.PublicKey;
5 import java.security.cert.CertPathBuilder;
6 import java.security.cert.CertPathBuilderException;
7 import java.security.cert.CertPathValidatorException;
8 import java.security.cert.X509CRL;
9 import java.security.cert.X509CRLSelector;
10 import java.security.cert.X509CertSelector;
11 import java.security.cert.X509Certificate;
12 import java.security.cert.X509Extension;
13 import java.util.ArrayList;
14 import java.util.Date;
15 import java.util.Enumeration;
16 import java.util.HashSet;
17 import java.util.Iterator;
18 import java.util.LinkedHashSet;
19 import java.util.List;
20 import java.util.Set;
21 
22 import org.bouncycastle.asn1.ASN1Encodable;
23 import org.bouncycastle.asn1.ASN1EncodableVector;
24 import org.bouncycastle.asn1.ASN1Primitive;
25 import org.bouncycastle.asn1.ASN1Sequence;
26 import org.bouncycastle.asn1.DERSequence;
27 import org.bouncycastle.asn1.x500.X500Name;
28 import org.bouncycastle.asn1.x509.BasicConstraints;
29 import org.bouncycastle.asn1.x509.CRLDistPoint;
30 import org.bouncycastle.asn1.x509.CRLReason;
31 import org.bouncycastle.asn1.x509.DistributionPoint;
32 import org.bouncycastle.asn1.x509.DistributionPointName;
33 import org.bouncycastle.asn1.x509.Extension;
34 import org.bouncycastle.asn1.x509.GeneralName;
35 import org.bouncycastle.asn1.x509.GeneralNames;
36 import org.bouncycastle.asn1.x509.IssuingDistributionPoint;
37 import org.bouncycastle.jcajce.PKIXCRLStoreSelector;
38 import org.bouncycastle.jcajce.PKIXCertStoreSelector;
39 import org.bouncycastle.jcajce.PKIXExtendedBuilderParameters;
40 import org.bouncycastle.jcajce.PKIXExtendedParameters;
41 import org.bouncycastle.jcajce.util.JcaJceHelper;
42 import org.bouncycastle.util.Arrays;
43 
44 class RFC3280CertPathUtilities
45 {
46     /**
47      * If the complete CRL includes an issuing distribution point (IDP) CRL
48      * extension check the following:
49      * <p>
50      * (i) If the distribution point name is present in the IDP CRL extension
51      * and the distribution field is present in the DP, then verify that one of
52      * the names in the IDP matches one of the names in the DP. If the
53      * distribution point name is present in the IDP CRL extension and the
54      * distribution field is omitted from the DP, then verify that one of the
55      * names in the IDP matches one of the names in the cRLIssuer field of the
56      * DP.
57      * </p>
58      * <p>
59      * (ii) If the onlyContainsUserCerts boolean is asserted in the IDP CRL
60      * extension, verify that the certificate does not include the basic
61      * constraints extension with the cA boolean asserted.
62      * </p>
63      * <p>
64      * (iii) If the onlyContainsCACerts boolean is asserted in the IDP CRL
65      * extension, verify that the certificate includes the basic constraints
66      * extension with the cA boolean asserted.
67      * </p>
68      * <p>
69      * (iv) Verify that the onlyContainsAttributeCerts boolean is not asserted.
70      * </p>
71      *
72      * @param dp   The distribution point.
73      * @param cert The certificate.
74      * @param crl  The CRL.
75      * @throws AnnotatedException if one of the conditions is not met or an error occurs.
76      */
processCRLB2( DistributionPoint dp, Object cert, X509CRL crl)77     protected static void processCRLB2(
78         DistributionPoint dp,
79         Object cert,
80         X509CRL crl)
81         throws AnnotatedException
82     {
83         IssuingDistributionPoint idp = null;
84         try
85         {
86             idp = IssuingDistributionPoint.getInstance(RevocationUtilities.getExtensionValue(crl,
87                 Extension.issuingDistributionPoint));
88         }
89         catch (Exception e)
90         {
91             throw new AnnotatedException("Issuing distribution point extension could not be decoded.", e);
92         }
93         // (b) (2) (i)
94         // distribution point name is present
95         if (idp != null)
96         {
97             if (idp.getDistributionPoint() != null)
98             {
99                 // make list of names
100                 DistributionPointName dpName = IssuingDistributionPoint.getInstance(idp).getDistributionPoint();
101                 List names = new ArrayList();
102 
103                 if (dpName.getType() == DistributionPointName.FULL_NAME)
104                 {
105                     GeneralName[] genNames = GeneralNames.getInstance(dpName.getName()).getNames();
106                     for (int j = 0; j < genNames.length; j++)
107                     {
108                         names.add(genNames[j]);
109                     }
110                 }
111                 if (dpName.getType() == DistributionPointName.NAME_RELATIVE_TO_CRL_ISSUER)
112                 {
113                     ASN1EncodableVector vec = new ASN1EncodableVector();
114                     try
115                     {
116                         Enumeration e = ASN1Sequence.getInstance(crl.getIssuerX500Principal().getEncoded()).getObjects();
117                         while (e.hasMoreElements())
118                         {
119                             vec.add((ASN1Encodable)e.nextElement());
120                         }
121                     }
122                     catch (Exception e)
123                     {
124                         throw new AnnotatedException("Could not read CRL issuer.", e);
125                     }
126                     vec.add(dpName.getName());
127                     names.add(new GeneralName(X500Name.getInstance(new DERSequence(vec))));
128                 }
129                 boolean matches = false;
130                 // verify that one of the names in the IDP matches one
131                 // of the names in the DP.
132                 if (dp.getDistributionPoint() != null)
133                 {
134                     dpName = dp.getDistributionPoint();
135                     GeneralName[] genNames = null;
136                     if (dpName.getType() == DistributionPointName.FULL_NAME)
137                     {
138                         genNames = GeneralNames.getInstance(dpName.getName()).getNames();
139                     }
140                     if (dpName.getType() == DistributionPointName.NAME_RELATIVE_TO_CRL_ISSUER)
141                     {
142                         if (dp.getCRLIssuer() != null)
143                         {
144                             genNames = dp.getCRLIssuer().getNames();
145                         }
146                         else
147                         {
148                             genNames = new GeneralName[1];
149                             try
150                             {
151                                 genNames[0] = new GeneralName(X500Name.getInstance(((X509Certificate)cert).getIssuerX500Principal().getEncoded()));
152                             }
153                             catch (Exception e)
154                             {
155                                 throw new AnnotatedException("Could not read certificate issuer.", e);
156                             }
157                         }
158                         for (int j = 0; j < genNames.length; j++)
159                         {
160                             Enumeration e = ASN1Sequence.getInstance(genNames[j].getName().toASN1Primitive()).getObjects();
161                             ASN1EncodableVector vec = new ASN1EncodableVector();
162                             while (e.hasMoreElements())
163                             {
164                                 vec.add((ASN1Encodable)e.nextElement());
165                             }
166                             vec.add(dpName.getName());
167                             genNames[j] = new GeneralName(X500Name.getInstance(new DERSequence(vec)));
168                         }
169                     }
170                     if (genNames != null)
171                     {
172                         for (int j = 0; j < genNames.length; j++)
173                         {
174                             if (names.contains(genNames[j]))
175                             {
176                                 matches = true;
177                                 break;
178                             }
179                         }
180                     }
181                     if (!matches)
182                     {
183                         throw new AnnotatedException(
184                             "No match for certificate CRL issuing distribution point name to cRLIssuer CRL distribution point.");
185                     }
186                 }
187                 // verify that one of the names in
188                 // the IDP matches one of the names in the cRLIssuer field of
189                 // the DP
190                 else
191                 {
192                     if (dp.getCRLIssuer() == null)
193                     {
194                         throw new AnnotatedException("Either the cRLIssuer or the distributionPoint field must "
195                             + "be contained in DistributionPoint.");
196                     }
197                     GeneralName[] genNames = dp.getCRLIssuer().getNames();
198                     for (int j = 0; j < genNames.length; j++)
199                     {
200                         if (names.contains(genNames[j]))
201                         {
202                             matches = true;
203                             break;
204                         }
205                     }
206                     if (!matches)
207                     {
208                         throw new AnnotatedException(
209                             "No match for certificate CRL issuing distribution point name to cRLIssuer CRL distribution point.");
210                     }
211                 }
212             }
213             BasicConstraints bc = null;
214             try
215             {
216                 bc = BasicConstraints.getInstance(RevocationUtilities.getExtensionValue((X509Extension)cert,
217                     Extension.basicConstraints));
218             }
219             catch (Exception e)
220             {
221                 throw new AnnotatedException("Basic constraints extension could not be decoded.", e);
222             }
223 
224             if (cert instanceof X509Certificate)
225             {
226                 // (b) (2) (ii)
227                 if (idp.onlyContainsUserCerts() && (bc != null && bc.isCA()))
228                 {
229                     throw new AnnotatedException("CA Cert CRL only contains user certificates.");
230                 }
231 
232                 // (b) (2) (iii)
233                 if (idp.onlyContainsCACerts() && (bc == null || !bc.isCA()))
234                 {
235                     throw new AnnotatedException("End CRL only contains CA certificates.");
236                 }
237             }
238 
239             // (b) (2) (iv)
240             if (idp.onlyContainsAttributeCerts())
241             {
242                 throw new AnnotatedException("onlyContainsAttributeCerts boolean is asserted.");
243             }
244         }
245     }
246 
247     /**
248      * If the DP includes cRLIssuer, then verify that the issuer field in the
249      * complete CRL matches cRLIssuer in the DP and that the complete CRL
250      * contains an issuing distribution point extension with the indirectCRL
251      * boolean asserted. Otherwise, verify that the CRL issuer matches the
252      * certificate issuer.
253      *
254      * @param dp   The distribution point.
255      * @param cert The certificate ot attribute certificate.
256      * @param crl  The CRL for <code>cert</code>.
257      * @throws AnnotatedException if one of the above conditions does not apply or an error
258      *                            occurs.
259      */
processCRLB1( DistributionPoint dp, Object cert, X509CRL crl)260     protected static void processCRLB1(
261         DistributionPoint dp,
262         Object cert,
263         X509CRL crl)
264         throws AnnotatedException
265     {
266         ASN1Primitive idp = RevocationUtilities.getExtensionValue(crl, Extension.issuingDistributionPoint);
267         boolean isIndirect = false;
268         if (idp != null)
269         {
270             if (IssuingDistributionPoint.getInstance(idp).isIndirectCRL())
271             {
272                 isIndirect = true;
273             }
274         }
275         byte[] issuerBytes;
276 
277             issuerBytes = crl.getIssuerX500Principal().getEncoded();
278 
279 
280         boolean matchIssuer = false;
281         if (dp.getCRLIssuer() != null)
282         {
283             GeneralName genNames[] = dp.getCRLIssuer().getNames();
284             for (int j = 0; j < genNames.length; j++)
285             {
286                 if (genNames[j].getTagNo() == GeneralName.directoryName)
287                 {
288                     try
289                     {
290                         if (Arrays.areEqual(genNames[j].getName().toASN1Primitive().getEncoded(), issuerBytes))
291                         {
292                             matchIssuer = true;
293                         }
294                     }
295                     catch (IOException e)
296                     {
297                         throw new AnnotatedException(
298                             "CRL issuer information from distribution point cannot be decoded.", e);
299                     }
300                 }
301             }
302             if (matchIssuer && !isIndirect)
303             {
304                 throw new AnnotatedException("Distribution point contains cRLIssuer field but CRL is not indirect.");
305             }
306             if (!matchIssuer)
307             {
308                 throw new AnnotatedException("CRL issuer of CRL does not match CRL issuer of distribution point.");
309             }
310         }
311         else
312         {
313             if (crl.getIssuerX500Principal().equals(((X509Certificate)cert).getIssuerX500Principal()))
314             {
315                 matchIssuer = true;
316             }
317         }
318         if (!matchIssuer)
319         {
320             throw new AnnotatedException("Cannot find matching CRL issuer for certificate.");
321         }
322     }
323 
processCRLD( X509CRL crl, DistributionPoint dp)324     protected static ReasonsMask processCRLD(
325         X509CRL crl,
326         DistributionPoint dp)
327         throws AnnotatedException
328     {
329         IssuingDistributionPoint idp = null;
330         try
331         {
332             idp = IssuingDistributionPoint.getInstance(RevocationUtilities.getExtensionValue(crl,
333                 Extension.issuingDistributionPoint));
334         }
335         catch (Exception e)
336         {
337             throw new AnnotatedException("Issuing distribution point extension could not be decoded.", e);
338         }
339         // (d) (1)
340         if (idp != null && idp.getOnlySomeReasons() != null && dp.getReasons() != null)
341         {
342             return new ReasonsMask(dp.getReasons()).intersect(new ReasonsMask(idp.getOnlySomeReasons()));
343         }
344         // (d) (4)
345         if ((idp == null || idp.getOnlySomeReasons() == null) && dp.getReasons() == null)
346         {
347             return ReasonsMask.allReasons;
348         }
349         // (d) (2) and (d)(3)
350         return (dp.getReasons() == null
351             ? ReasonsMask.allReasons
352             : new ReasonsMask(dp.getReasons())).intersect(idp == null
353             ? ReasonsMask.allReasons
354             : new ReasonsMask(idp.getOnlySomeReasons()));
355 
356     }
357 
358 
359     public static final String ISSUING_DISTRIBUTION_POINT = Extension.issuingDistributionPoint.getId();
360 
361     public static final String FRESHEST_CRL = Extension.freshestCRL.getId();
362 
363     public static final String DELTA_CRL_INDICATOR = Extension.deltaCRLIndicator.getId();
364 
365     public static final String BASIC_CONSTRAINTS = Extension.basicConstraints.getId();
366 
367     public static final String AUTHORITY_KEY_IDENTIFIER = Extension.authorityKeyIdentifier.getId();
368 
369     /*
370      * key usage bits
371      */
372     protected static final int KEY_CERT_SIGN = 5;
373 
374     protected static final int CRL_SIGN = 6;
375 
376     /**
377      * Obtain and validate the certification path for the complete CRL issuer.
378      * If a key usage extension is present in the CRL issuer's certificate,
379      * verify that the cRLSign bit is set.
380      *
381      * @param crl                CRL which contains revocation information for the certificate
382      *                           <code>cert</code>.
383      * @param cert               The attribute certificate or certificate to check if it is
384      *                           revoked.
385      * @param defaultCRLSignCert The issuer certificate of the certificate <code>cert</code>.
386      * @param defaultCRLSignKey  The public key of the issuer certificate
387      *                           <code>defaultCRLSignCert</code>.
388      * @param paramsPKIX         PKIX parameters.
389      * @param certPathCerts      The certificates on the certification path.
390      * @return A <code>Set</code> with all keys of possible CRL issuer
391      *         certificates.
392      * @throws AnnotatedException if the CRL is not valid or the status cannot be checked or
393      *                            some error occurs.
394      */
processCRLF( X509CRL crl, Object cert, X509Certificate defaultCRLSignCert, PublicKey defaultCRLSignKey, PKIXExtendedParameters paramsPKIX, List certPathCerts, JcaJceHelper helper)395     protected static Set processCRLF(
396         X509CRL crl,
397         Object cert,
398         X509Certificate defaultCRLSignCert,
399         PublicKey defaultCRLSignKey,
400         PKIXExtendedParameters paramsPKIX,
401         List certPathCerts,
402         JcaJceHelper helper)
403         throws AnnotatedException
404     {
405         // (f)
406 
407         // get issuer from CRL
408         X509CertSelector certSelector = new X509CertSelector();
409         try
410         {
411             byte[] issuerPrincipal = crl.getIssuerX500Principal().getEncoded();
412             certSelector.setSubject(issuerPrincipal);
413         }
414         catch (IOException e)
415         {
416             throw new AnnotatedException(
417                 "subject criteria for certificate selector to find issuer certificate for CRL could not be set", e);
418         }
419 
420         PKIXCertStoreSelector selector = new PKIXCertStoreSelector.Builder(certSelector).build();
421 
422         // get CRL signing certs
423         LinkedHashSet coll = new LinkedHashSet();
424         try
425         {
426             RevocationUtilities.findCertificates(coll, selector, paramsPKIX.getCertificateStores());
427             RevocationUtilities.findCertificates(coll, selector, paramsPKIX.getCertStores());
428         }
429         catch (AnnotatedException e)
430         {
431             throw new AnnotatedException("Issuer certificate for CRL cannot be searched.", e);
432         }
433 
434         coll.add(defaultCRLSignCert);
435 
436         List validCerts = new ArrayList();
437         List validKeys = new ArrayList();
438 
439         Iterator cert_it = coll.iterator();
440         while (cert_it.hasNext())
441         {
442             X509Certificate signingCert = (X509Certificate)cert_it.next();
443 
444             /*
445              * CA of the certificate, for which this CRL is checked, has also
446              * signed CRL, so skip the path validation, because is already done
447              */
448             if (signingCert.equals(defaultCRLSignCert))
449             {
450                 validCerts.add(signingCert);
451                 validKeys.add(defaultCRLSignKey);
452                 continue;
453             }
454             try
455             {
456                 CertPathBuilder builder = helper.createCertPathBuilder("PKIX");
457                 X509CertSelector tmpCertSelector = new X509CertSelector();
458                 tmpCertSelector.setCertificate(signingCert);
459 
460                 PKIXExtendedParameters.Builder paramsBuilder = new PKIXExtendedParameters.Builder(paramsPKIX)
461                     .setTargetConstraints(new PKIXCertStoreSelector.Builder(tmpCertSelector).build());
462 
463                 /*
464                  * if signingCert is placed not higher on the cert path a
465                  * dependency loop results. CRL for cert is checked, but
466                  * signingCert is needed for checking the CRL which is dependent
467                  * on checking cert because it is higher in the cert path and so
468                  * signing signingCert transitively. so, revocation is disabled,
469                  * forgery attacks of the CRL are detected in this outer loop
470                  * for all other it must be enabled to prevent forgery attacks
471                  */
472                 if (certPathCerts.contains(signingCert))
473                 {
474                     paramsBuilder.setRevocationEnabled(false);
475                 }
476                 else
477                 {
478                     paramsBuilder.setRevocationEnabled(true);
479                 }
480 
481                 PKIXExtendedBuilderParameters extParams = new PKIXExtendedBuilderParameters.Builder(paramsBuilder.build()).build();
482 
483                 List certs = builder.build(extParams).getCertPath().getCertificates();
484                 validCerts.add(signingCert);
485                 validKeys.add(RevocationUtilities.getNextWorkingKey(certs, 0, helper));
486             }
487             catch (CertPathBuilderException e)
488             {
489                 throw new AnnotatedException("CertPath for CRL signer failed to validate.", e);
490             }
491             catch (CertPathValidatorException e)
492             {
493                 throw new AnnotatedException("Public key of issuer certificate of CRL could not be retrieved.", e);
494             }
495             catch (Exception e)
496             {
497                 throw new AnnotatedException(e.getMessage());
498             }
499         }
500 
501         Set checkKeys = new HashSet();
502 
503         AnnotatedException lastException = null;
504         for (int i = 0; i < validCerts.size(); i++)
505         {
506             X509Certificate signCert = (X509Certificate)validCerts.get(i);
507             boolean[] keyUsage = signCert.getKeyUsage();
508 
509             if (keyUsage != null && (keyUsage.length <= CRL_SIGN || !keyUsage[CRL_SIGN]))
510             {
511                 lastException = new AnnotatedException(
512                     "Issuer certificate key usage extension does not permit CRL signing.");
513             }
514             else
515             {
516                 checkKeys.add(validKeys.get(i));
517             }
518         }
519 
520         if (checkKeys.isEmpty() && lastException == null)
521         {
522             throw new AnnotatedException("Cannot find a valid issuer certificate.");
523         }
524         if (checkKeys.isEmpty() && lastException != null)
525         {
526             throw lastException;
527         }
528 
529         return checkKeys;
530     }
531 
processCRLG( X509CRL crl, Set keys)532     protected static PublicKey processCRLG(
533         X509CRL crl,
534         Set keys)
535         throws AnnotatedException
536     {
537         Exception lastException = null;
538         for (Iterator it = keys.iterator(); it.hasNext();)
539         {
540             PublicKey key = (PublicKey)it.next();
541             try
542             {
543                 crl.verify(key);
544                 return key;
545             }
546             catch (Exception e)
547             {
548                 lastException = e;
549             }
550         }
551         throw new AnnotatedException("Cannot verify CRL.", lastException);
552     }
553 
processCRLH( Set deltacrls, PublicKey key)554     protected static X509CRL processCRLH(
555         Set deltacrls,
556         PublicKey key)
557         throws AnnotatedException
558     {
559         Exception lastException = null;
560 
561         for (Iterator it = deltacrls.iterator(); it.hasNext();)
562         {
563             X509CRL crl = (X509CRL)it.next();
564             try
565             {
566                 crl.verify(key);
567                 return crl;
568             }
569             catch (Exception e)
570             {
571                 lastException = e;
572             }
573         }
574 
575         if (lastException != null)
576         {
577             throw new AnnotatedException("Cannot verify delta CRL.", lastException);
578         }
579         return null;
580     }
581 
processCRLA1i( PKIXExtendedParameters paramsPKIX, Date currentDate, X509Certificate cert, X509CRL crl)582     protected static Set processCRLA1i(
583         PKIXExtendedParameters paramsPKIX,
584         Date currentDate,
585         X509Certificate cert,
586         X509CRL crl)
587         throws AnnotatedException
588     {
589         Set set = new HashSet();
590         if (paramsPKIX.isUseDeltasEnabled())
591         {
592             CRLDistPoint freshestCRL = null;
593             try
594             {
595                 freshestCRL = CRLDistPoint
596                     .getInstance(RevocationUtilities.getExtensionValue(cert, Extension.freshestCRL));
597             }
598             catch (AnnotatedException e)
599             {
600                 throw new AnnotatedException("Freshest CRL extension could not be decoded from certificate.", e);
601             }
602             if (freshestCRL == null)
603             {
604                 try
605                 {
606                     freshestCRL = CRLDistPoint.getInstance(RevocationUtilities.getExtensionValue(crl,
607                         Extension.freshestCRL));
608                 }
609                 catch (AnnotatedException e)
610                 {
611                     throw new AnnotatedException("Freshest CRL extension could not be decoded from CRL.", e);
612                 }
613             }
614             if (freshestCRL != null)
615             {
616                 List crlStores = new ArrayList();
617 
618                 crlStores.addAll(paramsPKIX.getCRLStores());
619 
620                 try
621                 {
622                     crlStores.addAll(RevocationUtilities.getAdditionalStoresFromCRLDistributionPoint(freshestCRL, paramsPKIX.getNamedCRLStoreMap()));
623                 }
624                 catch (AnnotatedException e)
625                 {
626                     throw new AnnotatedException(
627                         "No new delta CRL locations could be added from Freshest CRL extension.", e);
628                 }
629 
630                 // get delta CRL(s)
631                 try
632                 {
633                     set.addAll(RevocationUtilities.getDeltaCRLs(currentDate, crl, paramsPKIX.getCertStores(), crlStores));
634                 }
635                 catch (AnnotatedException e)
636                 {
637                     throw new AnnotatedException("Exception obtaining delta CRLs.", e);
638                 }
639             }
640         }
641         return set;
642     }
643 
processCRLA1ii( PKIXExtendedParameters paramsPKIX, Date currentDate, Date validityDate, X509Certificate cert, X509CRL crl)644     protected static Set[] processCRLA1ii(
645         PKIXExtendedParameters paramsPKIX,
646         Date currentDate,
647         Date validityDate,
648         X509Certificate cert,
649         X509CRL crl)
650         throws AnnotatedException
651     {
652         X509CRLSelector crlselect = new X509CRLSelector();
653         crlselect.setCertificateChecking(cert);
654 
655         try
656         {
657             crlselect.addIssuerName(crl.getIssuerX500Principal().getEncoded());
658         }
659         catch (IOException e)
660         {
661             throw new AnnotatedException("Cannot extract issuer from CRL." + e, e);
662         }
663 
664         PKIXCRLStoreSelector extSelect = new PKIXCRLStoreSelector.Builder(crlselect).setCompleteCRLEnabled(true).build();
665 
666         Set completeSet = PKIXCRLUtil.findCRLs(extSelect, validityDate, paramsPKIX.getCertStores(),
667             paramsPKIX.getCRLStores());
668         Set deltaSet = new HashSet();
669 
670         if (paramsPKIX.isUseDeltasEnabled())
671         {
672             // get delta CRL(s)
673             try
674             {
675                 deltaSet.addAll(RevocationUtilities.getDeltaCRLs(validityDate, crl, paramsPKIX.getCertStores(), paramsPKIX.getCRLStores()));
676             }
677             catch (AnnotatedException e)
678             {
679                 throw new AnnotatedException("Exception obtaining delta CRLs.", e);
680             }
681         }
682         return new Set[]{ completeSet, deltaSet };
683     }
684 
685     /**
686      * If use-deltas is set, verify the issuer and scope of the delta CRL.
687      *
688      * @param deltaCRL    The delta CRL.
689      * @param completeCRL The complete CRL.
690      * @param pkixParams  The PKIX paramaters.
691      * @throws AnnotatedException if an exception occurs.
692      */
processCRLC( X509CRL deltaCRL, X509CRL completeCRL, PKIXExtendedParameters pkixParams)693     protected static void processCRLC(
694         X509CRL deltaCRL,
695         X509CRL completeCRL,
696         PKIXExtendedParameters pkixParams)
697         throws AnnotatedException
698     {
699         if (deltaCRL == null)
700         {
701             return;
702         }
703         IssuingDistributionPoint completeidp = null;
704         try
705         {
706             completeidp = IssuingDistributionPoint.getInstance(RevocationUtilities.getExtensionValue(
707                 completeCRL, Extension.issuingDistributionPoint));
708         }
709         catch (Exception e)
710         {
711             throw new AnnotatedException("issuing distribution point extension could not be decoded.", e);
712         }
713 
714         if (pkixParams.isUseDeltasEnabled())
715         {
716             // (c) (1)
717             if (!deltaCRL.getIssuerX500Principal().equals(completeCRL.getIssuerX500Principal()))
718             {
719                 throw new AnnotatedException("complete CRL issuer does not match delta CRL issuer");
720             }
721 
722             // (c) (2)
723             IssuingDistributionPoint deltaidp = null;
724             try
725             {
726                 deltaidp = IssuingDistributionPoint.getInstance(RevocationUtilities.getExtensionValue(
727                     deltaCRL, Extension.issuingDistributionPoint));
728             }
729             catch (Exception e)
730             {
731                 throw new AnnotatedException(
732                     "Issuing distribution point extension from delta CRL could not be decoded.", e);
733             }
734 
735             boolean match = false;
736             if (completeidp == null)
737             {
738                 if (deltaidp == null)
739                 {
740                     match = true;
741                 }
742             }
743             else
744             {
745                 if (completeidp.equals(deltaidp))
746                 {
747                     match = true;
748                 }
749             }
750             if (!match)
751             {
752                 throw new AnnotatedException(
753                     "Issuing distribution point extension from delta CRL and complete CRL does not match.");
754             }
755 
756             // (c) (3)
757             ASN1Primitive completeKeyIdentifier = null;
758             try
759             {
760                 completeKeyIdentifier = RevocationUtilities.getExtensionValue(
761                     completeCRL, Extension.authorityKeyIdentifier);
762             }
763             catch (AnnotatedException e)
764             {
765                 throw new AnnotatedException(
766                     "Authority key identifier extension could not be extracted from complete CRL.", e);
767             }
768 
769             ASN1Primitive deltaKeyIdentifier = null;
770             try
771             {
772                 deltaKeyIdentifier = RevocationUtilities.getExtensionValue(
773                     deltaCRL, Extension.authorityKeyIdentifier);
774             }
775             catch (AnnotatedException e)
776             {
777                 throw new AnnotatedException(
778                     "Authority key identifier extension could not be extracted from delta CRL.", e);
779             }
780 
781             if (completeKeyIdentifier == null)
782             {
783                 throw new AnnotatedException("CRL authority key identifier is null.");
784             }
785 
786             if (deltaKeyIdentifier == null)
787             {
788                 throw new AnnotatedException("Delta CRL authority key identifier is null.");
789             }
790 
791             if (!completeKeyIdentifier.equals(deltaKeyIdentifier))
792             {
793                 throw new AnnotatedException(
794                     "Delta CRL authority key identifier does not match complete CRL authority key identifier.");
795             }
796         }
797     }
798 
processCRLI( Date validDate, X509CRL deltacrl, Object cert, CertStatus certStatus, PKIXExtendedParameters pkixParams)799     protected static void processCRLI(
800         Date validDate,
801         X509CRL deltacrl,
802         Object cert,
803         CertStatus certStatus,
804         PKIXExtendedParameters pkixParams)
805         throws AnnotatedException
806     {
807         if (pkixParams.isUseDeltasEnabled() && deltacrl != null)
808         {
809             RevocationUtilities.getCertStatus(validDate, deltacrl, cert, certStatus);
810         }
811     }
812 
processCRLJ( Date validDate, X509CRL completecrl, Object cert, CertStatus certStatus)813     protected static void processCRLJ(
814         Date validDate,
815         X509CRL completecrl,
816         Object cert,
817         CertStatus certStatus)
818         throws AnnotatedException
819     {
820         if (certStatus.getCertStatus() == CertStatus.UNREVOKED)
821         {
822             RevocationUtilities.getCertStatus(validDate, completecrl, cert, certStatus);
823         }
824     }
825 
826     /**
827      * Checks a distribution point for revocation information for the
828      * certificate <code>cert</code>.
829      *
830      * @param dp                 The distribution point to consider.
831      * @param paramsPKIX         PKIX parameters.
832      * @param cert               Certificate to check if it is revoked.
833      * @param validDate          The date when the certificate revocation status should be
834      *                           checked.
835      * @param defaultCRLSignCert The issuer certificate of the certificate <code>cert</code>.
836      * @param defaultCRLSignKey  The public key of the issuer certificate
837      *                           <code>defaultCRLSignCert</code>.
838      * @param certStatus         The current certificate revocation status.
839      * @param reasonMask         The reasons mask which is already checked.
840      * @param certPathCerts      The certificates of the certification path.
841      * @throws AnnotatedException if the certificate is revoked or the status cannot be checked
842      *                            or some error occurs.
843      */
checkCRL( DistributionPoint dp, PKIXExtendedParameters paramsPKIX, Date currentDate, Date validityDate, X509Certificate cert, X509Certificate defaultCRLSignCert, PublicKey defaultCRLSignKey, CertStatus certStatus, ReasonsMask reasonMask, List certPathCerts, JcaJceHelper helper)844     static void checkCRL(
845         DistributionPoint dp,
846         PKIXExtendedParameters paramsPKIX,
847         Date currentDate,
848         Date validityDate,
849         X509Certificate cert,
850         X509Certificate defaultCRLSignCert,
851         PublicKey defaultCRLSignKey,
852         CertStatus certStatus,
853         ReasonsMask reasonMask,
854         List certPathCerts,
855         JcaJceHelper helper)
856         throws AnnotatedException, CRLNotFoundException
857     {
858         if (validityDate.getTime() > currentDate.getTime())
859         {
860             throw new AnnotatedException("Validation time is in future.");
861         }
862 
863         // (a)
864         /*
865          * We always get timely valid CRLs, so there is no step (a) (1).
866          * "locally cached" CRLs are assumed to be in getStore(), additional
867          * CRLs must be enabled in the ExtendedPKIXParameters and are in
868          * getAdditionalStore()
869          */
870 
871         Set crls = RevocationUtilities.getCompleteCRLs(dp, cert, validityDate, paramsPKIX.getCertStores(), paramsPKIX.getCRLStores());
872         boolean validCrlFound = false;
873         AnnotatedException lastException = null;
874         Iterator crl_iter = crls.iterator();
875 
876         while (crl_iter.hasNext() && certStatus.getCertStatus() == CertStatus.UNREVOKED && !reasonMask.isAllReasons())
877         {
878             try
879             {
880                 X509CRL crl = (X509CRL)crl_iter.next();
881 
882                 // (d)
883                 ReasonsMask interimReasonsMask = RFC3280CertPathUtilities.processCRLD(crl, dp);
884 
885                 // (e)
886                 /*
887                  * The reasons mask is updated at the end, so only valid CRLs
888                  * can update it. If this CRL does not contain new reasons it
889                  * must be ignored.
890                  */
891                 if (!interimReasonsMask.hasNewReasons(reasonMask))
892                 {
893                     continue;
894                 }
895 
896                 // (f)
897                 Set keys = RFC3280CertPathUtilities.processCRLF(crl, cert, defaultCRLSignCert, defaultCRLSignKey,
898                     paramsPKIX, certPathCerts, helper);
899                 // (g)
900                 PublicKey key = RFC3280CertPathUtilities.processCRLG(crl, keys);
901 
902                 X509CRL deltaCRL = null;
903 
904                 if (paramsPKIX.isUseDeltasEnabled())
905                 {
906                     // get delta CRLs
907                     Set deltaCRLs = RevocationUtilities.getDeltaCRLs(validityDate, crl, paramsPKIX.getCertStores(), paramsPKIX.getCRLStores());
908                     // we only want one valid delta CRL
909                     // (h)
910                     deltaCRL = RFC3280CertPathUtilities.processCRLH(deltaCRLs, key);
911                 }
912 
913                 /*
914                  * CRL must be be valid at the current time, not the validation
915                  * time. If a certificate is revoked with reason keyCompromise,
916                  * cACompromise, it can be used for forgery, also for the past.
917                  * This reason may not be contained in older CRLs.
918                  */
919 
920                 /*
921                  * in the chain model signatures stay valid also after the
922                  * certificate has been expired, so they do not have to be in
923                  * the CRL validity time
924                  */
925 
926                 if (paramsPKIX.getValidityModel() != PKIXExtendedParameters.CHAIN_VALIDITY_MODEL)
927                 {
928                     /*
929                      * if a certificate has expired, but was revoked, it is not
930                      * more in the CRL, so it would be regarded as valid if the
931                      * first check is not done
932                      */
933                     if (cert.getNotAfter().getTime() < crl.getThisUpdate().getTime())
934                     {
935                         throw new AnnotatedException("No valid CRL for current time found.");
936                     }
937                 }
938 
939                 RFC3280CertPathUtilities.processCRLB1(dp, cert, crl);
940 
941                 // (b) (2)
942                 RFC3280CertPathUtilities.processCRLB2(dp, cert, crl);
943 
944                 // (c)
945                 RFC3280CertPathUtilities.processCRLC(deltaCRL, crl, paramsPKIX);
946 
947                 // (i)
948                 RFC3280CertPathUtilities.processCRLI(validityDate, deltaCRL, cert, certStatus, paramsPKIX);
949 
950                 // (j)
951                 RFC3280CertPathUtilities.processCRLJ(validityDate, crl, cert, certStatus);
952 
953                 // (k)
954                 if (certStatus.getCertStatus() == CRLReason.removeFromCRL)
955                 {
956                     certStatus.setCertStatus(CertStatus.UNREVOKED);
957                 }
958 
959                 // update reasons mask
960                 reasonMask.addReasons(interimReasonsMask);
961 
962                 Set criticalExtensions = crl.getCriticalExtensionOIDs();
963                 if (criticalExtensions != null)
964                 {
965                     criticalExtensions = new HashSet(criticalExtensions);
966                     criticalExtensions.remove(Extension.issuingDistributionPoint.getId());
967                     criticalExtensions.remove(Extension.deltaCRLIndicator.getId());
968 
969                     if (!criticalExtensions.isEmpty())
970                     {
971                         throw new AnnotatedException("CRL contains unsupported critical extensions.");
972                     }
973                 }
974 
975                 if (deltaCRL != null)
976                 {
977                     criticalExtensions = deltaCRL.getCriticalExtensionOIDs();
978                     if (criticalExtensions != null)
979                     {
980                         criticalExtensions = new HashSet(criticalExtensions);
981                         criticalExtensions.remove(Extension.issuingDistributionPoint.getId());
982                         criticalExtensions.remove(Extension.deltaCRLIndicator.getId());
983                         if (!criticalExtensions.isEmpty())
984                         {
985                             throw new AnnotatedException("Delta CRL contains unsupported critical extension.");
986                         }
987                     }
988                 }
989 
990                 validCrlFound = true;
991             }
992             catch (AnnotatedException e)
993             {
994                 lastException = e;
995             }
996         }
997         if (!validCrlFound)
998         {
999             throw lastException;
1000         }
1001     }
1002 }
1003