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