1 package org.bouncycastle.x509;
2 
3 import org.bouncycastle.util.Selector;
4 import org.bouncycastle.util.Store;
5 
6 import java.security.InvalidAlgorithmParameterException;
7 import org.bouncycastle.jce.cert.CertSelector;
8 import org.bouncycastle.jce.cert.CertStore;
9 import org.bouncycastle.jce.cert.CollectionCertStoreParameters;
10 import org.bouncycastle.jce.cert.LDAPCertStoreParameters;
11 import org.bouncycastle.jce.cert.PKIXParameters;
12 import org.bouncycastle.jce.cert.TrustAnchor;
13 import org.bouncycastle.jce.cert.X509CertSelector;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.HashSet;
18 import java.util.Iterator;
19 import java.util.List;
20 import java.util.Set;
21 
22 /**
23  * This class extends the PKIXParameters with a validity model parameter.
24  */
25 public class ExtendedPKIXParameters
26     extends PKIXParameters
27 {
28 
29     private List stores;
30 
31     private Selector selector;
32 
33     private boolean additionalLocationsEnabled;
34 
35     private List additionalStores;
36 
37     private Set trustedACIssuers;
38 
39     private Set necessaryACAttributes;
40 
41     private Set prohibitedACAttributes;
42 
43     private Set attrCertCheckers;
44 
45     /**
46      * Creates an instance of <code>PKIXParameters</code> with the specified
47      * <code>Set</code> of most-trusted CAs. Each element of the set is a
48      * {@link TrustAnchor TrustAnchor}.
49      * <p>
50      *     Note that the <code>Set</code>
51      * is copied to protect against subsequent modifications.
52      * </p>
53      *
54      * @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s
55      * @throws InvalidAlgorithmParameterException if the specified
56      *             <code>Set</code> is empty.
57      * @throws NullPointerException if the specified <code>Set</code> is
58      *             <code>null</code>
59      * @throws ClassCastException if any of the elements in the <code>Set</code>
60      *             is not of type <code>java.security.cert.TrustAnchor</code>
61      */
ExtendedPKIXParameters(Set trustAnchors)62     public ExtendedPKIXParameters(Set trustAnchors)
63         throws InvalidAlgorithmParameterException
64     {
65         super(trustAnchors);
66         stores = new ArrayList();
67         additionalStores = new ArrayList();
68         trustedACIssuers = new HashSet();
69         necessaryACAttributes = new HashSet();
70         prohibitedACAttributes = new HashSet();
71         attrCertCheckers = new HashSet();
72     }
73 
74     /**
75      * Returns an instance with the parameters of a given
76      * <code>PKIXParameters</code> object.
77      *
78      * @param pkixParams The given <code>PKIXParameters</code>
79      * @return an extended PKIX params object
80      */
getInstance(PKIXParameters pkixParams)81     public static ExtendedPKIXParameters getInstance(PKIXParameters pkixParams)
82     {
83         ExtendedPKIXParameters params;
84         try
85         {
86             params = new ExtendedPKIXParameters(pkixParams.getTrustAnchors());
87         }
88         catch (Exception e)
89         {
90             // cannot happen
91             throw new RuntimeException(e.getMessage());
92         }
93         params.setParams(pkixParams);
94         return params;
95     }
96 
97     /**
98      * Method to support <code>clone()</code> under J2ME.
99      * <code>super.clone()</code> does not exist and fields are not copied.
100      *
101      * @param params Parameters to set. If this are
102      *            <code>ExtendedPKIXParameters</code> they are copied to.
103      */
setParams(PKIXParameters params)104     protected void setParams(PKIXParameters params)
105     {
106         setDate(params.getDate());
107         setCertPathCheckers(params.getCertPathCheckers());
108         setCertStores(params.getCertStores());
109         setAnyPolicyInhibited(params.isAnyPolicyInhibited());
110         setExplicitPolicyRequired(params.isExplicitPolicyRequired());
111         setPolicyMappingInhibited(params.isPolicyMappingInhibited());
112         setRevocationEnabled(params.isRevocationEnabled());
113         setInitialPolicies(params.getInitialPolicies());
114         setPolicyQualifiersRejected(params.getPolicyQualifiersRejected());
115         setSigProvider(params.getSigProvider());
116         setTargetCertConstraints(params.getTargetCertConstraints());
117         try
118         {
119             setTrustAnchors(params.getTrustAnchors());
120         }
121         catch (Exception e)
122         {
123             // cannot happen
124             throw new RuntimeException(e.getMessage());
125         }
126         if (params instanceof ExtendedPKIXParameters)
127         {
128             ExtendedPKIXParameters _params = (ExtendedPKIXParameters) params;
129             validityModel = _params.validityModel;
130             useDeltas = _params.useDeltas;
131             additionalLocationsEnabled = _params.additionalLocationsEnabled;
132             selector = _params.selector == null ? null
133                 : (Selector) _params.selector.clone();
134             stores = new ArrayList(_params.stores);
135             additionalStores = new ArrayList(_params.additionalStores);
136             trustedACIssuers = new HashSet(_params.trustedACIssuers);
137             prohibitedACAttributes = new HashSet(_params.prohibitedACAttributes);
138             necessaryACAttributes = new HashSet(_params.necessaryACAttributes);
139             attrCertCheckers = new HashSet(_params.attrCertCheckers);
140         }
141     }
142 
143     /**
144      * This is the default PKIX validity model. Actually there are two variants
145      * of this: The PKIX model and the modified PKIX model. The PKIX model
146      * verifies that all involved certificates must have been valid at the
147      * current time. The modified PKIX model verifies that all involved
148      * certificates were valid at the signing time. Both are indirectly choosen
149      * with the {@link PKIXParameters#setDate(java.util.Date)} method, so this
150      * methods sets the Date when <em>all</em> certificates must have been
151      * valid.
152      */
153     public static final int PKIX_VALIDITY_MODEL = 0;
154 
155     /**
156      * This model uses the following validity model. Each certificate must have
157      * been valid at the moment where is was used. That means the end
158      * certificate must have been valid at the time the signature was done. The
159      * CA certificate which signed the end certificate must have been valid,
160      * when the end certificate was signed. The CA (or Root CA) certificate must
161      * have been valid, when the CA certificate was signed and so on. So the
162      * {@link PKIXParameters#setDate(java.util.Date)} method sets the time, when
163      * the <em>end certificate</em> must have been valid.
164      * <p>
165      * It is used e.g. in the German signature law.
166      * </p>
167      */
168     public static final int CHAIN_VALIDITY_MODEL = 1;
169 
170     private int validityModel = PKIX_VALIDITY_MODEL;
171 
172     private boolean useDeltas = false;
173 
174     /**
175      * Defaults to <code>false</code>.
176      *
177      * @return Returns if delta CRLs should be used.
178      */
isUseDeltasEnabled()179     public boolean isUseDeltasEnabled()
180     {
181         return useDeltas;
182     }
183 
184     /**
185      * Sets if delta CRLs should be used for checking the revocation status.
186      *
187      * @param useDeltas <code>true</code> if delta CRLs should be used.
188      */
setUseDeltasEnabled(boolean useDeltas)189     public void setUseDeltasEnabled(boolean useDeltas)
190     {
191         this.useDeltas = useDeltas;
192     }
193 
194     /**
195      * @return Returns the validity model.
196      * @see #CHAIN_VALIDITY_MODEL
197      * @see #PKIX_VALIDITY_MODEL
198      */
getValidityModel()199     public int getValidityModel()
200     {
201         return validityModel;
202     }
203 
204     /**
205      * Sets the Java CertStore to this extended PKIX parameters.
206      *
207      * @throws ClassCastException if an element of <code>stores</code> is not
208      *             a <code>CertStore</code>.
209      */
setCertStores(List stores)210     public void setCertStores(List stores)
211     {
212         if (stores != null)
213         {
214             Iterator it = stores.iterator();
215             while (it.hasNext())
216             {
217                 addCertStore((CertStore)it.next());
218             }
219         }
220     }
221 
222     /**
223      * Sets the Bouncy Castle Stores for finding CRLs, certificates, attribute
224      * certificates or cross certificates.
225      * <p>
226      * The <code>List</code> is cloned.
227      *
228      * @param stores A list of stores to use.
229      * @see #getStores
230      * @throws ClassCastException if an element of <code>stores</code> is not
231      *             a {@link Store}.
232      */
setStores(List stores)233     public void setStores(List stores)
234     {
235         if (stores == null)
236         {
237             this.stores = new ArrayList();
238         }
239         else
240         {
241             for (Iterator i = stores.iterator(); i.hasNext();)
242             {
243                 if (!(i.next() instanceof Store))
244                 {
245                     throw new ClassCastException(
246                         "All elements of list must be "
247                             + "of type org.bouncycastle.util.Store.");
248                 }
249             }
250             this.stores = new ArrayList(stores);
251         }
252     }
253 
254     /**
255      * Adds a Bouncy Castle {@link Store} to find CRLs, certificates, attribute
256      * certificates or cross certificates.
257      * <p>
258      * This method should be used to add local stores, like collection based
259      * X.509 stores, if available. Local stores should be considered first,
260      * before trying to use additional (remote) locations, because they do not
261      * need possible additional network traffic.
262      * <p>
263      * If <code>store</code> is <code>null</code> it is ignored.
264      *
265      * @param store The store to add.
266      * @see #getStores
267      */
addStore(Store store)268     public void addStore(Store store)
269     {
270         if (stores != null)
271         {
272             stores.add(store);
273         }
274     }
275 
276     /**
277      * Adds a additional Bouncy Castle {@link Store} to find CRLs, certificates,
278      * attribute certificates or cross certificates.
279      * <p>
280      * You should not use this method. This method is used for adding additional
281      * X.509 stores, which are used to add (remote) locations, e.g. LDAP, found
282      * during X.509 object processing, e.g. in certificates or CRLs. This method
283      * is used in PKIX certification path processing.
284      * <p>
285      * If <code>store</code> is <code>null</code> it is ignored.
286      *
287      * @param store The store to add.
288      * @see #getStores()
289      */
addAddionalStore(Store store)290     public void addAddionalStore(Store store)
291     {
292         if (store != null)
293         {
294             additionalStores.add(store);
295         }
296     }
297 
298     /**
299      * Returns an immutable <code>List</code> of additional Bouncy Castle
300      * <code>Store</code>s used for finding CRLs, certificates, attribute
301      * certificates or cross certificates.
302      *
303      * @return an immutable <code>List</code> of additional Bouncy Castle
304      *         <code>Store</code>s. Never <code>null</code>.
305      *
306      * @see #addAddionalStore(Store)
307      */
getAdditionalStores()308     public List getAdditionalStores()
309     {
310         return Collections.unmodifiableList(additionalStores);
311     }
312 
313     /**
314      * Returns an immutable <code>List</code> of Bouncy Castle
315      * <code>Store</code>s used for finding CRLs, certificates, attribute
316      * certificates or cross certificates.
317      *
318      * @return an immutable <code>List</code> of Bouncy Castle
319      *         <code>Store</code>s. Never <code>null</code>.
320      *
321      * @see #setStores(List)
322      */
getStores()323     public List getStores()
324     {
325         return Collections.unmodifiableList(new ArrayList(stores));
326     }
327 
328     /**
329      * @param validityModel The validity model to set.
330      * @see #CHAIN_VALIDITY_MODEL
331      * @see #PKIX_VALIDITY_MODEL
332      */
setValidityModel(int validityModel)333     public void setValidityModel(int validityModel)
334     {
335         this.validityModel = validityModel;
336     }
337 
clone()338     public Object clone()
339     {
340         ExtendedPKIXParameters params;
341         try
342         {
343             params = new ExtendedPKIXParameters(getTrustAnchors());
344         }
345         catch (Exception e)
346         {
347             // cannot happen
348             throw new RuntimeException(e.getMessage());
349         }
350         params.setParams(this);
351         return params;
352     }
353 
354     /**
355      * Returns if additional {@link X509Store}s for locations like LDAP found
356      * in certificates or CRLs should be used.
357      *
358      * @return Returns <code>true</code> if additional stores are used.
359      */
isAdditionalLocationsEnabled()360     public boolean isAdditionalLocationsEnabled()
361     {
362         return additionalLocationsEnabled;
363     }
364 
365     /**
366      * Sets if additional {@link X509Store}s for locations like LDAP found in
367      * certificates or CRLs should be used.
368      *
369      * @param enabled <code>true</code> if additional stores are used.
370      */
setAdditionalLocationsEnabled(boolean enabled)371     public void setAdditionalLocationsEnabled(boolean enabled)
372     {
373         additionalLocationsEnabled = enabled;
374     }
375 
376     /**
377      * Returns the required constraints on the target certificate or attribute
378      * certificate. The constraints are returned as an instance of
379      * <code>Selector</code>. If <code>null</code>, no constraints are
380      * defined.
381      *
382      * <p>
383      * The target certificate in a PKIX path may be a certificate or an
384      * attribute certificate.
385      * <p>
386      * Note that the <code>Selector</code> returned is cloned to protect
387      * against subsequent modifications.
388      *
389      * @return a <code>Selector</code> specifying the constraints on the
390      *         target certificate or attribute certificate (or <code>null</code>)
391      * @see #setTargetConstraints
392      * @see X509CertStoreSelector
393      * @see X509AttributeCertStoreSelector
394      */
getTargetConstraints()395     public Selector getTargetConstraints()
396     {
397         if (selector != null)
398         {
399             return (Selector) selector.clone();
400         }
401         else
402         {
403             return null;
404         }
405     }
406 
407     /**
408      * Sets the required constraints on the target certificate or attribute
409      * certificate. The constraints are specified as an instance of
410      * <code>Selector</code>. If <code>null</code>, no constraints are
411      * defined.
412      * <p>
413      * The target certificate in a PKIX path may be a certificate or an
414      * attribute certificate.
415      * <p>
416      * Note that the <code>Selector</code> specified is cloned to protect
417      * against subsequent modifications.
418      *
419      * @param selector a <code>Selector</code> specifying the constraints on
420      *            the target certificate or attribute certificate (or
421      *            <code>null</code>)
422      * @see #getTargetConstraints
423      * @see X509CertStoreSelector
424      * @see X509AttributeCertStoreSelector
425      */
setTargetConstraints(Selector selector)426     public void setTargetConstraints(Selector selector)
427     {
428         if (selector != null)
429         {
430             this.selector = (Selector) selector.clone();
431         }
432         else
433         {
434             this.selector = null;
435         }
436     }
437 
438     /**
439      * Sets the required constraints on the target certificate. The constraints
440      * are specified as an instance of <code>X509CertSelector</code>. If
441      * <code>null</code>, no constraints are defined.
442      *
443      * <p>
444      * This method wraps the given <code>X509CertSelector</code> into a
445      * <code>X509CertStoreSelector</code>.
446      * <p>
447      * Note that the <code>X509CertSelector</code> specified is cloned to
448      * protect against subsequent modifications.
449      *
450      * @param selector a <code>X509CertSelector</code> specifying the
451      *            constraints on the target certificate (or <code>null</code>)
452      * @see #getTargetCertConstraints
453      * @see X509CertStoreSelector
454      */
setTargetCertConstraints(CertSelector selector)455     public void setTargetCertConstraints(CertSelector selector)
456     {
457         super.setTargetCertConstraints(selector);
458         if (selector != null)
459         {
460             this.selector = X509CertStoreSelector
461                 .getInstance((X509CertSelector) selector);
462         }
463         else
464         {
465             this.selector = null;
466         }
467     }
468 
469     /**
470      * Returns the trusted attribute certificate issuers. If attribute
471      * certificates is verified the trusted AC issuers must be set.
472      * <p>
473      * The returned <code>Set</code> consists of <code>TrustAnchor</code>s.
474      * <p>
475      * The returned <code>Set</code> is immutable. Never <code>null</code>
476      *
477      * @return Returns an immutable set of the trusted AC issuers.
478      */
getTrustedACIssuers()479     public Set getTrustedACIssuers()
480     {
481         return Collections.unmodifiableSet(trustedACIssuers);
482     }
483 
484     /**
485      * Sets the trusted attribute certificate issuers. If attribute certificates
486      * is verified the trusted AC issuers must be set.
487      * <p>
488      * The <code>trustedACIssuers</code> must be a <code>Set</code> of
489      * <code>TrustAnchor</code>
490      * <p>
491      * The given set is cloned.
492      *
493      * @param trustedACIssuers The trusted AC issuers to set. Is never
494      *            <code>null</code>.
495      * @throws ClassCastException if an element of <code>stores</code> is not
496      *             a <code>TrustAnchor</code>.
497      */
setTrustedACIssuers(Set trustedACIssuers)498     public void setTrustedACIssuers(Set trustedACIssuers)
499     {
500         if (trustedACIssuers == null)
501         {
502             trustedACIssuers.clear();
503             return;
504         }
505         for (Iterator it = trustedACIssuers.iterator(); it.hasNext();)
506         {
507             if (!(it.next() instanceof TrustAnchor))
508             {
509                 throw new ClassCastException("All elements of set must be "
510                     + "of type " + TrustAnchor.class.getName() + ".");
511             }
512         }
513         this.trustedACIssuers.clear();
514         this.trustedACIssuers.addAll(trustedACIssuers);
515     }
516 
517     /**
518      * Returns the neccessary attributes which must be contained in an attribute
519      * certificate.
520      * <p>
521      * The returned <code>Set</code> is immutable and contains
522      * <code>String</code>s with the OIDs.
523      *
524      * @return Returns the necessary AC attributes.
525      */
getNecessaryACAttributes()526     public Set getNecessaryACAttributes()
527     {
528         return Collections.unmodifiableSet(necessaryACAttributes);
529     }
530 
531     /**
532      * Sets the neccessary which must be contained in an attribute certificate.
533      * <p>
534      * The <code>Set</code> must contain <code>String</code>s with the
535      * OIDs.
536      * <p>
537      * The set is cloned.
538      *
539      * @param necessaryACAttributes The necessary AC attributes to set.
540      * @throws ClassCastException if an element of
541      *             <code>necessaryACAttributes</code> is not a
542      *             <code>String</code>.
543      */
setNecessaryACAttributes(Set necessaryACAttributes)544     public void setNecessaryACAttributes(Set necessaryACAttributes)
545     {
546         if (necessaryACAttributes == null)
547         {
548             this.necessaryACAttributes.clear();
549             return;
550         }
551         for (Iterator it = necessaryACAttributes.iterator(); it.hasNext();)
552         {
553             if (!(it.next() instanceof String))
554             {
555                 throw new ClassCastException("All elements of set must be "
556                     + "of type String.");
557             }
558         }
559         this.necessaryACAttributes.clear();
560         this.necessaryACAttributes.addAll(necessaryACAttributes);
561     }
562 
563     /**
564      * Returns the attribute certificates which are not allowed.
565      * <p>
566      * The returned <code>Set</code> is immutable and contains
567      * <code>String</code>s with the OIDs.
568      *
569      * @return Returns the prohibited AC attributes. Is never <code>null</code>.
570      */
getProhibitedACAttributes()571     public Set getProhibitedACAttributes()
572     {
573         return prohibitedACAttributes;
574     }
575 
576     /**
577      * Sets the attribute certificates which are not allowed.
578      * <p>
579      * The <code>Set</code> must contain <code>String</code>s with the
580      * OIDs.
581      * <p>
582      * The set is cloned.
583      *
584      * @param prohibitedACAttributes The prohibited AC attributes to set.
585      * @throws ClassCastException if an element of
586      *             <code>prohibitedACAttributes</code> is not a
587      *             <code>String</code>.
588      */
setProhibitedACAttributes(Set prohibitedACAttributes)589     public void setProhibitedACAttributes(Set prohibitedACAttributes)
590     {
591         if (prohibitedACAttributes == null)
592         {
593             this.prohibitedACAttributes.clear();
594             return;
595         }
596         for (Iterator it = prohibitedACAttributes.iterator(); it.hasNext();)
597         {
598             if (!(it.next() instanceof String))
599             {
600                 throw new ClassCastException("All elements of set must be "
601                     + "of type String.");
602             }
603         }
604         this.prohibitedACAttributes.clear();
605         this.prohibitedACAttributes.addAll(prohibitedACAttributes);
606     }
607 
608     /**
609      * Returns the attribute certificate checker. The returned set contains
610      * {@link PKIXAttrCertChecker}s and is immutable.
611      *
612      * @return Returns the attribute certificate checker. Is never
613      *         <code>null</code>.
614      */
getAttrCertCheckers()615     public Set getAttrCertCheckers()
616     {
617         return Collections.unmodifiableSet(attrCertCheckers);
618     }
619 
620     /**
621      * Sets the attribute certificate checkers.
622      * <p>
623      * All elements in the <code>Set</code> must a {@link PKIXAttrCertChecker}.
624      * <p>
625      * The given set is cloned.
626      *
627      * @param attrCertCheckers The attribute certificate checkers to set. Is
628      *            never <code>null</code>.
629      * @throws ClassCastException if an element of <code>attrCertCheckers</code>
630      *             is not a <code>PKIXAttrCertChecker</code>.
631      */
632 /*
633     public void setAttrCertCheckers(Set attrCertCheckers)
634     {
635         if (attrCertCheckers == null)
636         {
637             this.attrCertCheckers.clear();
638             return;
639         }
640         for (Iterator it = attrCertCheckers.iterator(); it.hasNext();)
641         {
642             if (!(it.next() instanceof PKIXAttrCertChecker))
643             {
644                 throw new ClassCastException("All elements of set must be "
645                     + "of type " + PKIXAttrCertChecker.class.getName() + ".");
646             }
647         }
648         this.attrCertCheckers.clear();
649         this.attrCertCheckers.addAll(attrCertCheckers);
650     }
651 */
652 }
653