1package org.bouncycastle.jcajce;
2
3import java.security.cert.CertPathParameters;
4import java.security.cert.CertSelector;
5import java.security.cert.CertStore;
6import java.security.cert.PKIXParameters;
7import java.security.cert.TrustAnchor;
8import java.util.ArrayList;
9import java.util.Collections;
10import java.util.Date;
11import java.util.HashMap;
12import java.util.List;
13import java.util.Map;
14import java.util.Set;
15
16import org.bouncycastle.asn1.x509.GeneralName;
17
18/**
19 * This class extends the PKIXParameters with a validity model parameter.
20 */
21public class PKIXExtendedParameters
22    implements CertPathParameters
23{
24    /**
25     * This is the default PKIX validity model. Actually there are two variants
26     * of this: The PKIX model and the modified PKIX model. The PKIX model
27     * verifies that all involved certificates must have been valid at the
28     * current time. The modified PKIX model verifies that all involved
29     * certificates were valid at the signing time. Both are indirectly choosen
30     * with the {@link PKIXParameters#setDate(Date)} method, so this
31     * methods sets the Date when <em>all</em> certificates must have been
32     * valid.
33     */
34    public static final int PKIX_VALIDITY_MODEL = 0;
35
36    /**
37     * This model uses the following validity model. Each certificate must have
38     * been valid at the moment where is was used. That means the end
39     * certificate must have been valid at the time the signature was done. The
40     * CA certificate which signed the end certificate must have been valid,
41     * when the end certificate was signed. The CA (or Root CA) certificate must
42     * have been valid, when the CA certificate was signed and so on. So the
43     * {@link PKIXParameters#setDate(Date)} method sets the time, when
44     * the <em>end certificate</em> must have been valid. <p/> It is used e.g.
45     * in the German signature law.
46     */
47    public static final int CHAIN_VALIDITY_MODEL = 1;
48
49    /**
50     * Builder for a PKIXExtendedParameters object.
51     */
52    public static class Builder
53    {
54        private final PKIXParameters baseParameters;
55        private final Date date;
56
57        private PKIXCertStoreSelector targetConstraints;
58        private List<PKIXCertStore> extraCertStores = new ArrayList<PKIXCertStore>();
59        private Map<GeneralName, PKIXCertStore> namedCertificateStoreMap = new HashMap<GeneralName, PKIXCertStore>();
60        private List<PKIXCRLStore> extraCRLStores = new ArrayList<PKIXCRLStore>();
61        private Map<GeneralName, PKIXCRLStore> namedCRLStoreMap = new HashMap<GeneralName, PKIXCRLStore>();
62        private boolean revocationEnabled;
63        private int validityModel = PKIX_VALIDITY_MODEL;
64        private boolean useDeltas = false;
65        private Set<TrustAnchor> trustAnchors;
66
67        public Builder(PKIXParameters baseParameters)
68        {
69            this.baseParameters = (PKIXParameters)baseParameters.clone();
70            CertSelector constraints = baseParameters.getTargetCertConstraints();
71            if (constraints != null)
72            {
73                this.targetConstraints = new PKIXCertStoreSelector.Builder(constraints).build();
74            }
75            Date checkDate = baseParameters.getDate();
76            this.date = (checkDate == null) ? new Date() : checkDate;
77            this.revocationEnabled = baseParameters.isRevocationEnabled();
78            this.trustAnchors = baseParameters.getTrustAnchors();
79        }
80
81        public Builder(PKIXExtendedParameters baseParameters)
82        {
83            this.baseParameters = baseParameters.baseParameters;
84            this.date = baseParameters.date;
85            this.targetConstraints = baseParameters.targetConstraints;
86            this.extraCertStores = new ArrayList<PKIXCertStore>(baseParameters.extraCertStores);
87            this.namedCertificateStoreMap = new HashMap<GeneralName, PKIXCertStore>(baseParameters.namedCertificateStoreMap);
88            this.extraCRLStores = new ArrayList<PKIXCRLStore>(baseParameters.extraCRLStores);
89            this.namedCRLStoreMap = new HashMap<GeneralName, PKIXCRLStore>(baseParameters.namedCRLStoreMap);
90            this.useDeltas = baseParameters.useDeltas;
91            this.validityModel = baseParameters.validityModel;
92            this.revocationEnabled = baseParameters.isRevocationEnabled();
93            this.trustAnchors = baseParameters.getTrustAnchors();
94        }
95
96        public Builder addCertificateStore(PKIXCertStore store)
97        {
98            extraCertStores.add(store);
99
100            return this;
101        }
102
103        public Builder addNamedCertificateStore(GeneralName issuerAltName, PKIXCertStore store)
104        {
105            namedCertificateStoreMap.put(issuerAltName, store);
106
107            return this;
108        }
109
110        public Builder addCRLStore(PKIXCRLStore store)
111        {
112            extraCRLStores.add(store);
113
114            return this;
115        }
116
117        public Builder addNamedCRLStore(GeneralName issuerAltName, PKIXCRLStore store)
118        {
119            namedCRLStoreMap.put(issuerAltName, store);
120
121            return this;
122        }
123
124        public Builder setTargetConstraints(PKIXCertStoreSelector selector)
125        {
126            targetConstraints = selector;
127
128            return this;
129        }
130
131        /**
132         * Sets if delta CRLs should be used for checking the revocation status.
133         *
134         * @param useDeltas <code>true</code> if delta CRLs should be used.
135         */
136        public Builder setUseDeltasEnabled(boolean useDeltas)
137        {
138            this.useDeltas = useDeltas;
139
140            return this;
141        }
142
143        /**
144         * @param validityModel The validity model to set.
145         * @see #CHAIN_VALIDITY_MODEL
146         * @see #PKIX_VALIDITY_MODEL
147         */
148        public Builder setValidityModel(int validityModel)
149        {
150            this.validityModel = validityModel;
151
152            return this;
153        }
154
155        /**
156         * Set the trustAnchor to be used with these parameters.
157         *
158         * @param trustAnchor the trust anchor end-entity and CRLs must be based on.
159         * @return the current builder.
160         */
161        public Builder setTrustAnchor(TrustAnchor trustAnchor)
162        {
163            this.trustAnchors = Collections.singleton(trustAnchor);
164
165            return this;
166        }
167
168        /**
169         * Set the set of trustAnchors to be used with these parameters.
170         *
171         * @param trustAnchors  a set of trustAnchors, one of which a particular end-entity and it's associated CRLs must be based on.
172         * @return the current builder.
173         */
174        public Builder setTrustAnchors(Set<TrustAnchor> trustAnchors)
175        {
176            this.trustAnchors = trustAnchors;
177
178            return this;
179        }
180
181        /**
182         * Flag whether or not revocation checking is to be enabled.
183         *
184         * @param revocationEnabled  true if revocation checking to be enabled, false otherwise.
185         */
186        public void setRevocationEnabled(boolean revocationEnabled)
187        {
188            this.revocationEnabled = revocationEnabled;
189        }
190
191        public PKIXExtendedParameters build()
192        {
193            return new PKIXExtendedParameters(this);
194        }
195    }
196
197    private final PKIXParameters baseParameters;
198    private final PKIXCertStoreSelector targetConstraints;
199    private final Date date;
200    private final List<PKIXCertStore> extraCertStores;
201    private final Map<GeneralName, PKIXCertStore> namedCertificateStoreMap;
202    private final List<PKIXCRLStore> extraCRLStores;
203    private final Map<GeneralName, PKIXCRLStore> namedCRLStoreMap;
204    private final boolean revocationEnabled;
205    private final boolean useDeltas;
206    private final int validityModel;
207    private final Set<TrustAnchor> trustAnchors;
208
209    private PKIXExtendedParameters(Builder builder)
210    {
211        this.baseParameters = builder.baseParameters;
212        this.date = builder.date;
213        this.extraCertStores = Collections.unmodifiableList(builder.extraCertStores);
214        this.namedCertificateStoreMap = Collections.unmodifiableMap(new HashMap<GeneralName, PKIXCertStore>(builder.namedCertificateStoreMap));
215        this.extraCRLStores = Collections.unmodifiableList(builder.extraCRLStores);
216        this.namedCRLStoreMap = Collections.unmodifiableMap(new HashMap<GeneralName, PKIXCRLStore>(builder.namedCRLStoreMap));
217        this.targetConstraints = builder.targetConstraints;
218        this.revocationEnabled = builder.revocationEnabled;
219        this.useDeltas = builder.useDeltas;
220        this.validityModel = builder.validityModel;
221        this.trustAnchors = Collections.unmodifiableSet(builder.trustAnchors);
222    }
223
224    public List<PKIXCertStore> getCertificateStores()
225    {
226        return extraCertStores;
227    }
228
229
230    public Map<GeneralName, PKIXCertStore> getNamedCertificateStoreMap()
231    {
232        return namedCertificateStoreMap;
233    }
234
235    public List<PKIXCRLStore> getCRLStores()
236    {
237        return extraCRLStores;
238    }
239
240    public Map<GeneralName, PKIXCRLStore> getNamedCRLStoreMap()
241    {
242        return namedCRLStoreMap;
243    }
244
245    public Date getDate()
246    {
247        return new Date(date.getTime());
248    }
249
250
251
252
253    /**
254     * Defaults to <code>false</code>.
255     *
256     * @return Returns if delta CRLs should be used.
257     */
258    public boolean isUseDeltasEnabled()
259    {
260        return useDeltas;
261    }
262
263
264
265    /**
266     * @return Returns the validity model.
267     * @see #CHAIN_VALIDITY_MODEL
268     * @see #PKIX_VALIDITY_MODEL
269     */
270    public int getValidityModel()
271    {
272        return validityModel;
273    }
274
275    public Object clone()
276    {
277        return this;
278    }
279
280    /**
281     * Returns the required constraints on the target certificate.
282     * The constraints are returned as an instance of
283     * <code>Selector</code>. If <code>null</code>, no constraints are
284     * defined.
285     *
286     * @return a <code>Selector</code> specifying the constraints on the
287     *         target certificate or attribute certificate (or <code>null</code>)
288     * @see PKIXCertStoreSelector
289     */
290    public PKIXCertStoreSelector getTargetConstraints()
291    {
292        return targetConstraints;
293    }
294
295    public Set getTrustAnchors()
296    {
297        return trustAnchors;
298    }
299
300    public Set getInitialPolicies()
301    {
302        return baseParameters.getInitialPolicies();
303    }
304
305    public String getSigProvider()
306    {
307        return baseParameters.getSigProvider();
308    }
309
310    public boolean isExplicitPolicyRequired()
311    {
312        return baseParameters.isExplicitPolicyRequired();
313    }
314
315    public boolean isAnyPolicyInhibited()
316    {
317        return baseParameters.isAnyPolicyInhibited();
318    }
319
320    public boolean isPolicyMappingInhibited()
321    {
322        return baseParameters.isPolicyMappingInhibited();
323    }
324
325    public List getCertPathCheckers()
326    {
327        return baseParameters.getCertPathCheckers();
328    }
329
330    public List<CertStore> getCertStores()
331    {
332        return baseParameters.getCertStores();
333    }
334
335    public boolean isRevocationEnabled()
336    {
337        return revocationEnabled;
338    }
339
340}
341