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 java.security.cert.CertSelector; 8 import java.security.cert.CertStore; 9 import java.security.cert.PKIXParameters; 10 import java.security.cert.TrustAnchor; 11 import java.security.cert.X509CertSelector; 12 import java.util.ArrayList; 13 import java.util.Collections; 14 import java.util.HashSet; 15 import java.util.Iterator; 16 import java.util.List; 17 import java.util.Set; 18 19 /** 20 * This class extends the PKIXParameters with a validity model parameter. 21 */ 22 public class ExtendedPKIXParameters 23 extends PKIXParameters 24 { 25 26 private List stores; 27 28 private Selector selector; 29 30 private boolean additionalLocationsEnabled; 31 32 private List additionalStores; 33 34 private Set trustedACIssuers; 35 36 private Set necessaryACAttributes; 37 38 private Set prohibitedACAttributes; 39 40 private Set attrCertCheckers; 41 42 /** 43 * Creates an instance of <code>PKIXParameters</code> with the specified 44 * <code>Set</code> of most-trusted CAs. Each element of the set is a 45 * {@link TrustAnchor TrustAnchor}. <p/> Note that the <code>Set</code> 46 * is copied to protect against subsequent modifications. 47 * 48 * @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s 49 * @throws InvalidAlgorithmParameterException if the specified 50 * <code>Set</code> is empty. 51 * @throws NullPointerException if the specified <code>Set</code> is 52 * <code>null</code> 53 * @throws ClassCastException if any of the elements in the <code>Set</code> 54 * is not of type <code>java.security.cert.TrustAnchor</code> 55 */ ExtendedPKIXParameters(Set trustAnchors)56 public ExtendedPKIXParameters(Set trustAnchors) 57 throws InvalidAlgorithmParameterException 58 { 59 super(trustAnchors); 60 stores = new ArrayList(); 61 additionalStores = new ArrayList(); 62 trustedACIssuers = new HashSet(); 63 necessaryACAttributes = new HashSet(); 64 prohibitedACAttributes = new HashSet(); 65 attrCertCheckers = new HashSet(); 66 } 67 68 /** 69 * Returns an instance with the parameters of a given 70 * <code>PKIXParameters</code> object. 71 * 72 * @param pkixParams The given <code>PKIXParameters</code> 73 * @return an extended PKIX params object 74 */ getInstance(PKIXParameters pkixParams)75 public static ExtendedPKIXParameters getInstance(PKIXParameters pkixParams) 76 { 77 ExtendedPKIXParameters params; 78 try 79 { 80 params = new ExtendedPKIXParameters(pkixParams.getTrustAnchors()); 81 } 82 catch (Exception e) 83 { 84 // cannot happen 85 throw new RuntimeException(e.getMessage()); 86 } 87 params.setParams(pkixParams); 88 return params; 89 } 90 91 /** 92 * Method to support <code>clone()</code> under J2ME. 93 * <code>super.clone()</code> does not exist and fields are not copied. 94 * 95 * @param params Parameters to set. If this are 96 * <code>ExtendedPKIXParameters</code> they are copied to. 97 */ setParams(PKIXParameters params)98 protected void setParams(PKIXParameters params) 99 { 100 setDate(params.getDate()); 101 setCertPathCheckers(params.getCertPathCheckers()); 102 setCertStores(params.getCertStores()); 103 setAnyPolicyInhibited(params.isAnyPolicyInhibited()); 104 setExplicitPolicyRequired(params.isExplicitPolicyRequired()); 105 setPolicyMappingInhibited(params.isPolicyMappingInhibited()); 106 setRevocationEnabled(params.isRevocationEnabled()); 107 setInitialPolicies(params.getInitialPolicies()); 108 setPolicyQualifiersRejected(params.getPolicyQualifiersRejected()); 109 setSigProvider(params.getSigProvider()); 110 setTargetCertConstraints(params.getTargetCertConstraints()); 111 try 112 { 113 setTrustAnchors(params.getTrustAnchors()); 114 } 115 catch (Exception e) 116 { 117 // cannot happen 118 throw new RuntimeException(e.getMessage()); 119 } 120 if (params instanceof ExtendedPKIXParameters) 121 { 122 ExtendedPKIXParameters _params = (ExtendedPKIXParameters) params; 123 validityModel = _params.validityModel; 124 useDeltas = _params.useDeltas; 125 additionalLocationsEnabled = _params.additionalLocationsEnabled; 126 selector = _params.selector == null ? null 127 : (Selector) _params.selector.clone(); 128 stores = new ArrayList(_params.stores); 129 additionalStores = new ArrayList(_params.additionalStores); 130 trustedACIssuers = new HashSet(_params.trustedACIssuers); 131 prohibitedACAttributes = new HashSet(_params.prohibitedACAttributes); 132 necessaryACAttributes = new HashSet(_params.necessaryACAttributes); 133 attrCertCheckers = new HashSet(_params.attrCertCheckers); 134 } 135 } 136 137 /** 138 * This is the default PKIX validity model. Actually there are two variants 139 * of this: The PKIX model and the modified PKIX model. The PKIX model 140 * verifies that all involved certificates must have been valid at the 141 * current time. The modified PKIX model verifies that all involved 142 * certificates were valid at the signing time. Both are indirectly choosen 143 * with the {@link PKIXParameters#setDate(java.util.Date)} method, so this 144 * methods sets the Date when <em>all</em> certificates must have been 145 * valid. 146 */ 147 public static final int PKIX_VALIDITY_MODEL = 0; 148 149 /** 150 * This model uses the following validity model. Each certificate must have 151 * been valid at the moment where is was used. That means the end 152 * certificate must have been valid at the time the signature was done. The 153 * CA certificate which signed the end certificate must have been valid, 154 * when the end certificate was signed. The CA (or Root CA) certificate must 155 * have been valid, when the CA certificate was signed and so on. So the 156 * {@link PKIXParameters#setDate(java.util.Date)} method sets the time, when 157 * the <em>end certificate</em> must have been valid. <p/> It is used e.g. 158 * in the German signature law. 159 */ 160 public static final int CHAIN_VALIDITY_MODEL = 1; 161 162 private int validityModel = PKIX_VALIDITY_MODEL; 163 164 private boolean useDeltas = false; 165 166 /** 167 * Defaults to <code>false</code>. 168 * 169 * @return Returns if delta CRLs should be used. 170 */ isUseDeltasEnabled()171 public boolean isUseDeltasEnabled() 172 { 173 return useDeltas; 174 } 175 176 /** 177 * Sets if delta CRLs should be used for checking the revocation status. 178 * 179 * @param useDeltas <code>true</code> if delta CRLs should be used. 180 */ setUseDeltasEnabled(boolean useDeltas)181 public void setUseDeltasEnabled(boolean useDeltas) 182 { 183 this.useDeltas = useDeltas; 184 } 185 186 /** 187 * @return Returns the validity model. 188 * @see #CHAIN_VALIDITY_MODEL 189 * @see #PKIX_VALIDITY_MODEL 190 */ getValidityModel()191 public int getValidityModel() 192 { 193 return validityModel; 194 } 195 196 /** 197 * Sets the Java CertStore to this extended PKIX parameters. 198 * 199 * @throws ClassCastException if an element of <code>stores</code> is not 200 * a <code>CertStore</code>. 201 */ setCertStores(List stores)202 public void setCertStores(List stores) 203 { 204 if (stores != null) 205 { 206 Iterator it = stores.iterator(); 207 while (it.hasNext()) 208 { 209 addCertStore((CertStore)it.next()); 210 } 211 } 212 } 213 214 /** 215 * Sets the Bouncy Castle Stores for finding CRLs, certificates, attribute 216 * certificates or cross certificates. 217 * <p> 218 * The <code>List</code> is cloned. 219 * 220 * @param stores A list of stores to use. 221 * @see #getStores 222 * @throws ClassCastException if an element of <code>stores</code> is not 223 * a {@link Store}. 224 */ setStores(List stores)225 public void setStores(List stores) 226 { 227 if (stores == null) 228 { 229 this.stores = new ArrayList(); 230 } 231 else 232 { 233 for (Iterator i = stores.iterator(); i.hasNext();) 234 { 235 if (!(i.next() instanceof Store)) 236 { 237 throw new ClassCastException( 238 "All elements of list must be " 239 + "of type org.bouncycastle.util.Store."); 240 } 241 } 242 this.stores = new ArrayList(stores); 243 } 244 } 245 246 /** 247 * Adds a Bouncy Castle {@link Store} to find CRLs, certificates, attribute 248 * certificates or cross certificates. 249 * <p> 250 * This method should be used to add local stores, like collection based 251 * X.509 stores, if available. Local stores should be considered first, 252 * before trying to use additional (remote) locations, because they do not 253 * need possible additional network traffic. 254 * <p> 255 * If <code>store</code> is <code>null</code> it is ignored. 256 * 257 * @param store The store to add. 258 * @see #getStores 259 */ addStore(Store store)260 public void addStore(Store store) 261 { 262 if (store != null) 263 { 264 stores.add(store); 265 } 266 } 267 268 /** 269 * Adds an additional Bouncy Castle {@link Store} to find CRLs, certificates, 270 * attribute certificates or cross certificates. 271 * <p> 272 * You should not use this method. This method is used for adding additional 273 * X.509 stores, which are used to add (remote) locations, e.g. LDAP, found 274 * during X.509 object processing, e.g. in certificates or CRLs. This method 275 * is used in PKIX certification path processing. 276 * <p> 277 * If <code>store</code> is <code>null</code> it is ignored. 278 * 279 * @param store The store to add. 280 * @see #getStores() 281 */ addAdditionalStore(Store store)282 public void addAdditionalStore(Store store) 283 { 284 if (store != null) 285 { 286 additionalStores.add(store); 287 } 288 } 289 290 /** 291 * @deprecated 292 */ addAddionalStore(Store store)293 public void addAddionalStore(Store store) 294 { 295 addAdditionalStore(store); 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 #addAdditionalStore(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 this.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 Collections.unmodifiableSet(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 */ setAttrCertCheckers(Set attrCertCheckers)632 public void setAttrCertCheckers(Set attrCertCheckers) 633 { 634 if (attrCertCheckers == null) 635 { 636 this.attrCertCheckers.clear(); 637 return; 638 } 639 for (Iterator it = attrCertCheckers.iterator(); it.hasNext();) 640 { 641 if (!(it.next() instanceof PKIXAttrCertChecker)) 642 { 643 throw new ClassCastException("All elements of set must be " 644 + "of type " + PKIXAttrCertChecker.class.getName() + "."); 645 } 646 } 647 this.attrCertCheckers.clear(); 648 this.attrCertCheckers.addAll(attrCertCheckers); 649 } 650 651 } 652