1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.security.cert; 19 20import java.security.InvalidAlgorithmParameterException; 21import java.security.KeyStore; 22import java.security.KeyStoreException; 23import java.util.ArrayList; 24import java.util.Collections; 25import java.util.Date; 26import java.util.Enumeration; 27import java.util.HashSet; 28import java.util.Iterator; 29import java.util.List; 30import java.util.Set; 31 32/** 33 * This class implements the parameters for the {@code PKIX CertPathValidator}. 34 * <p> 35 * The parameters must be created with <i>trusted</i> certificate authorities 36 * (trust anchors). 37 * 38 * @see CertPathValidator 39 * @see CertPathParameters 40 */ 41public class PKIXParameters implements CertPathParameters { 42 // Set of trust anchors - most trusted CAs 43 private Set<TrustAnchor> trustAnchors; 44 // Set of acceptable initial policy identifiers (OID strings) 45 private Set<String> initialPolicies; 46 // List of cert stores that used to find certificates and CRLs 47 private List<CertStore> certStores; 48 // Time for which the validity of the certification 49 // patch should be determined 50 private Date date; 51 // List of certification patch checkers (PKIXCertPathChecker) 52 private List<PKIXCertPathChecker> certPathCheckers; 53 // Preferred signature provider name 54 private String sigProvider; 55 // Required constraints on the target certificate 56 private CertSelector targetCertConstraints; 57 // Indicates whether cert revocation is enabled or not 58 private boolean revocationEnabled = true; 59 // Indicates whether explicit policy required or not 60 private boolean explicitPolicyRequired = false; 61 // Indicates whether policy mapping inhibited or not 62 private boolean policyMappingInhibited = false; 63 // Indicates whether any policy inhibited or not 64 private boolean anyPolicyInhibited = false; 65 // Indicates whether certificates that include policy 66 // qualifiers in a certificate policies extension that 67 // is marked critical must be rejected or not 68 private boolean policyQualifiersRejected = true; 69 70 /** 71 * Creates a new {@code PKIXParameters} instance with the specified set of 72 * <i>trusted</i> certificate authorities. 73 * 74 * @param trustAnchors 75 * the trusted CAs. 76 * @throws InvalidAlgorithmParameterException 77 * if {@code trustAnchors} is empty. 78 */ 79 public PKIXParameters(Set<TrustAnchor> trustAnchors) 80 throws InvalidAlgorithmParameterException { 81 if (trustAnchors == null) { 82 throw new NullPointerException("trustAnchors == null"); 83 } 84 checkTrustAnchors(trustAnchors); 85 this.trustAnchors = new HashSet<TrustAnchor>(trustAnchors); 86 } 87 88 /** 89 * Creates a new {@code PKIXParameters} instance with the trusted {@code 90 * X509Certificate} entries from the specified {@code KeyStore}. 91 * 92 * @param keyStore 93 * the key store containing trusted certificates. 94 * @throws KeyStoreException 95 * if the {@code keyStore} is not initialized. 96 * @throws InvalidAlgorithmParameterException 97 * if {@code keyStore} does not contained any trusted 98 * certificate entry. 99 */ 100 public PKIXParameters(KeyStore keyStore) 101 throws KeyStoreException, 102 InvalidAlgorithmParameterException { 103 if (keyStore == null) { 104 throw new NullPointerException("keyStore == null"); 105 } 106 // Will throw KeyStoreException if 107 // keyStore has not been initialized (loaded) 108 if (keyStore.size() == 0) { 109 throw new InvalidAlgorithmParameterException("keyStore.size() == 0"); 110 } 111 // keyStore is not null and loaded 112 trustAnchors = new HashSet<TrustAnchor>(); 113 for (Enumeration i = keyStore.aliases(); i.hasMoreElements();) { 114 String alias = (String) i.nextElement(); 115 if (keyStore.isCertificateEntry(alias)) { 116 // this is trusted certificate entry 117 // check if it is X509Certificate 118 Certificate c = keyStore.getCertificate(alias); 119 // add only X509Certificate 120 // ignore all other types 121 if (c instanceof X509Certificate) { 122 trustAnchors.add(new TrustAnchor((X509Certificate)c, null)); 123 } 124 } 125 } 126 checkTrustAnchors(trustAnchors); 127 } 128 129 /** 130 * Returns a unmodifiable set of the <i>trusted</i> certificate authorities. 131 * 132 * @return a unmodifiable set of the <i>trusted</i> certificate authorities. 133 */ 134 public Set<TrustAnchor> getTrustAnchors() { 135 return Collections.unmodifiableSet(trustAnchors); 136 } 137 138 /** 139 * Sets the set of <i>trusted</i> certificate authorities. 140 * 141 * @param trustAnchors 142 * the set of <i>trusted</i> certificate authorities. 143 * @throws InvalidAlgorithmParameterException 144 * if {@code trustAnchors} is empty. 145 */ 146 public void setTrustAnchors(Set<TrustAnchor> trustAnchors) 147 throws InvalidAlgorithmParameterException { 148 if (trustAnchors == null) { 149 throw new NullPointerException("trustAnchors == null"); 150 } 151 checkTrustAnchors(trustAnchors); 152 // make shallow copy 153 this.trustAnchors = new HashSet<TrustAnchor>(trustAnchors); 154 } 155 156 /** 157 * Returns whether the <i>any policy OID</i> will be inhibited if it's 158 * included in a certificate. 159 * 160 * @return {@code true} if the <i>any policy OID</i> will be inhibited, 161 * otherwise {@code false}. 162 */ 163 public boolean isAnyPolicyInhibited() { 164 return anyPolicyInhibited; 165 } 166 167 /** 168 * Sets whether the <i>any policy OID</i> should be inhibited if it's 169 * included in a certificate. 170 * 171 * @param anyPolicyInhibited 172 * {@code true} if the <i>any policy OID</i> should be inhibited, 173 * otherwise {@code false}. 174 */ 175 public void setAnyPolicyInhibited(boolean anyPolicyInhibited) { 176 this.anyPolicyInhibited = anyPolicyInhibited; 177 } 178 179 /** 180 * Returns the list of checkers for the certification path. 181 * <p> 182 * The list is unmodifiable and the entries in the list are cloned. 183 * 184 * @return the list of checkers for the certification path. 185 */ 186 public List<PKIXCertPathChecker> getCertPathCheckers() { 187 if (certPathCheckers == null) { 188 // set to empty List if has not been set yet 189 certPathCheckers = new ArrayList<PKIXCertPathChecker>(); 190 } 191 if (certPathCheckers.isEmpty()) { 192 // no content - no need to copy, 193 // just return immutable view of the same 194 // empty List each time 195 return Collections.unmodifiableList(certPathCheckers); 196 } 197 // List is not empty - do deep copy 198 ArrayList<PKIXCertPathChecker> modifiableList = new ArrayList<PKIXCertPathChecker>(); 199 for (PKIXCertPathChecker certPathChecker : certPathCheckers) { 200 modifiableList.add((PKIXCertPathChecker) certPathChecker.clone()); 201 } 202 return Collections.unmodifiableList(modifiableList); 203 } 204 205 /** 206 * Sets the list of checkers for the certification path. 207 * <p> 208 * The list is copied and the entries are cloned. 209 * 210 * @param certPathCheckers 211 * the list of checkers for the certification path, or {@code 212 * null} to clear the checkers. 213 */ 214 public void setCertPathCheckers(List<PKIXCertPathChecker> certPathCheckers) { 215 if (certPathCheckers == null || certPathCheckers.isEmpty()) { 216 // empty list or null provided 217 if (this.certPathCheckers != null && 218 !this.certPathCheckers.isEmpty()) { 219 // discard non-empty list 220 this.certPathCheckers = null; 221 } 222 return; 223 } 224 // non-empty list provided - do deep copy 225 this.certPathCheckers = new ArrayList<PKIXCertPathChecker>(); 226 for (PKIXCertPathChecker certPathChecker : certPathCheckers) { 227 this.certPathCheckers.add((PKIXCertPathChecker) certPathChecker.clone()); 228 } 229 } 230 231 /** 232 * Adds the specified {@code PKIXCertPathChecker} to the list of 233 * certification path checkers. 234 * 235 * @param checker 236 * the {@code PKIXCertPathChecker} to add, if {@code null}, it 237 * will be ignored. 238 */ 239 public void addCertPathChecker(PKIXCertPathChecker checker) { 240 if (checker == null) { 241 // do nothing if null provided 242 return; 243 } 244 if (certPathCheckers == null) { 245 // set to empty List if has not been set yet 246 certPathCheckers = new ArrayList<PKIXCertPathChecker>(); 247 } 248 // add a copy to avoid possible modifications 249 certPathCheckers.add((PKIXCertPathChecker) checker.clone()); 250 } 251 252 /** 253 * Returns the list of certificate stores that are used to find certificates 254 * and CRLs. 255 * 256 * @return an immutable list of certificate stores. 257 */ 258 public List<CertStore> getCertStores() { 259 if (certStores == null) { 260 // set to empty List if has not been set yet 261 certStores = new ArrayList<CertStore>(); 262 } 263 if (certStores.isEmpty()) { 264 // no content - no need to copy, 265 // just return immutable view of the same 266 // empty List each time 267 return Collections.unmodifiableList(certStores); 268 } 269 // List is not empty - do shallow copy 270 ArrayList<CertStore> modifiableList 271 = new ArrayList<CertStore>(certStores); 272 return Collections.unmodifiableList(modifiableList); 273 } 274 275 /** 276 * Set the list of certificate stores that are used to find certificates and 277 * CRLs. 278 * 279 * @param certStores the list of certificate stores. 280 */ 281 public void setCertStores(List<CertStore> certStores) { 282 if (certStores == null || certStores.isEmpty()) { 283 // empty list or null provided 284 if (this.certStores != null && !this.certStores.isEmpty()) { 285 // discard non-empty list 286 this.certStores = null; 287 } 288 return; 289 } 290 // non-empty list provided - do shallow copy 291 this.certStores = new ArrayList<CertStore>(certStores); 292 } 293 294 /** 295 * Adds a certificate store to the list of certificate stores that are used 296 * to find certificates and CRLs. 297 * 298 * @param store 299 * the store to add, if {@code null}, it will be ignored. 300 */ 301 public void addCertStore(CertStore store) { 302 if (store == null) { 303 // do nothing if null provided 304 return; 305 } 306 if (certStores == null) { 307 // set to empty List if has not been set yet 308 certStores = new ArrayList<CertStore>(); 309 } 310 // add store 311 certStores.add(store); 312 } 313 314 /** 315 * Returns the time for which the validation of the certification path 316 * should be evaluated. 317 * 318 * @return the time for the validation, or {@code null} for the current 319 * time. 320 */ 321 public Date getDate() { 322 return date == null ? null : (Date)date.clone(); 323 } 324 325 /** 326 * Sets the time for which the validation of the certification path should be 327 * evaluated. 328 * 329 * @param date 330 * the time for the validation, or {@code null} for the current 331 * time. 332 */ 333 public void setDate(Date date) { 334 this.date = (date == null ? null : new Date(date.getTime())); 335 } 336 337 /** 338 * Returns whether an acceptable policy needs to be explicit identified in 339 * every certificate. 340 * 341 * @return {@code true} if an explicit policy is required, otherwise {@code 342 * false}. 343 */ 344 public boolean isExplicitPolicyRequired() { 345 return explicitPolicyRequired; 346 } 347 348 /** 349 * Sets whether an an acceptable policy needs to be explicit identified in 350 * every certificate. 351 * 352 * @param explicitPolicyRequired 353 * {@code true} if an explicit policy is required, otherwise 354 * {@code false}. 355 */ 356 public void setExplicitPolicyRequired(boolean explicitPolicyRequired) { 357 this.explicitPolicyRequired = explicitPolicyRequired; 358 } 359 360 /** 361 * Returns the list of policies (as OID strings) that would be acceptable 362 * for the purpose of certification path processing. 363 * 364 * @return the unmodifiable list of policies, or an empty set if any policy 365 * is acceptable. 366 */ 367 public Set<String> getInitialPolicies() { 368 if (initialPolicies == null) { 369 // set to empty Set if has not been set yet 370 initialPolicies = new HashSet<String>(); 371 } 372 if (initialPolicies.isEmpty()) { 373 // no content - no need to copy, 374 // just return immutable view of the same 375 // empty Set each time 376 return Collections.unmodifiableSet(initialPolicies); 377 } 378 // List is not empty - do shallow copy 379 HashSet<String> modifiableSet = new HashSet<String>(initialPolicies); 380 return Collections.unmodifiableSet(modifiableSet); 381 } 382 383 /** 384 * Sets the list of policies (as OID strings) that would be acceptable for 385 * the purpose of certification path processing. 386 * 387 * @param initialPolicies 388 * the list of policies, or an empty set or {@code null} if any 389 * policy is acceptable. 390 */ 391 public void setInitialPolicies(Set<String> initialPolicies) { 392 if (initialPolicies == null || initialPolicies.isEmpty()) { 393 // empty list or null provided 394 if (this.initialPolicies != null && !this.initialPolicies.isEmpty()) { 395 // discard non-empty list 396 this.initialPolicies = null; 397 } 398 return; 399 } 400 // non-empty list provided - do shallow copy 401 this.initialPolicies = new HashSet<String>(initialPolicies); 402 } 403 404 /** 405 * Returns whether policy mapping is inhibited. 406 * 407 * @return {@code true} if policy mapping is inhibited, otherwise {@code 408 * false}. 409 */ 410 public boolean isPolicyMappingInhibited() { 411 return policyMappingInhibited; 412 } 413 414 /** 415 * Sets whether policy mapping is to be inhibited. 416 * 417 * @param policyMappingInhibited 418 * {@code true} if policy mapping is to be inhibited, otherwise 419 * {@code false}. 420 */ 421 public void setPolicyMappingInhibited(boolean policyMappingInhibited) { 422 this.policyMappingInhibited = policyMappingInhibited; 423 } 424 425 /** 426 * Returns whether certificates are rejected that include policy 427 * qualifiers in a certificate policy extension that is marked as critical. 428 * 429 * @return {@code true} if the certificates should be rejected, otherwise 430 * {@code false}. 431 */ 432 public boolean getPolicyQualifiersRejected() { 433 return policyQualifiersRejected; 434 } 435 436 /** 437 * Sets whether certificates should be rejected that include policy 438 * qualifiers in a certificate policy extension that is marked as critical. 439 * 440 * @param policyQualifiersRejected 441 * {@code true} if the certificates should be rejected, otherwise 442 * {@code false}. 443 */ 444 public void setPolicyQualifiersRejected(boolean policyQualifiersRejected) { 445 this.policyQualifiersRejected = policyQualifiersRejected; 446 } 447 448 /** 449 * Returns whether the default revocation checking mechanism of the 450 * underlying service provider is used. 451 * 452 * @return {@code true} if the default revocation checking mechanism is 453 * used, otherwise {@code false}. 454 */ 455 public boolean isRevocationEnabled() { 456 return revocationEnabled; 457 } 458 459 /** 460 * Sets whether the default revocation checking mechanism of the underlying 461 * service provider should be used. 462 * 463 * @param revocationEnabled 464 * {@code true} id the default revocation checking mechanism 465 * should be used, otherwise {@code false}. 466 */ 467 public void setRevocationEnabled(boolean revocationEnabled) { 468 this.revocationEnabled = revocationEnabled; 469 } 470 471 /** 472 * Returns the name of the signature provider. 473 * 474 * @return the name of the signature provider, or {@code null} if none is 475 * set. 476 */ 477 public String getSigProvider() { 478 return sigProvider; 479 } 480 481 /** 482 * Sets the name of the preferred signature provider. 483 * <p> 484 * If set, the specified provider will be preferred for creating signatures. 485 * If not set, the first provider found supporting creation of signatures 486 * will be used. 487 * 488 * @param sigProvider 489 * the name of the preferred signature provider, or {@code null} 490 * if none is preferred. 491 */ 492 public void setSigProvider(String sigProvider) { 493 this.sigProvider = sigProvider; 494 } 495 496 /** 497 * Returns the constraints that are required for the target certificate. 498 * 499 * @return the constraints for the target certificate, or {@code null} if 500 * none are set. 501 */ 502 public CertSelector getTargetCertConstraints() { 503 return (targetCertConstraints == null ? null 504 :(CertSelector)targetCertConstraints.clone()); 505 } 506 507 /** 508 * Sets the constraints that are required for the target certificate. 509 * 510 * @param targetCertConstraints 511 * the constraints for the target certificate, or {@code null} if 512 * none should be used. 513 */ 514 public void setTargetCertConstraints(CertSelector targetCertConstraints) { 515 this.targetCertConstraints = (targetCertConstraints == null ? null 516 : (CertSelector)targetCertConstraints.clone()); 517 } 518 519 /** 520 * Clones this {@code PKIXParameters} instance. 521 * 522 * @return the cloned instance. 523 */ 524 public Object clone() { 525 try { 526 // do shallow copy first 527 PKIXParameters ret = (PKIXParameters)super.clone(); 528 // copy fields containing references to mutable objects 529 if (this.certStores != null) { 530 ret.certStores = new ArrayList<CertStore>(this.certStores); 531 } 532 if (this.certPathCheckers != null) { 533 ret.certPathCheckers = new ArrayList<PKIXCertPathChecker>(this.certPathCheckers); 534 } 535 return ret; 536 } catch (CloneNotSupportedException e) { 537 throw new AssertionError(e); 538 } 539 } 540 541 /** 542 * Returns a string representation of this {@code PKIXParameters} instance. 543 * 544 * @return a string representation of this {@code PKIXParameters} instance. 545 */ 546 public String toString() { 547 StringBuilder sb = 548 new StringBuilder("[\n Trust Anchors: "); 549 sb.append(trustAnchors); 550 sb.append("\n Revocation Enabled: "); 551 sb.append(revocationEnabled); 552 sb.append("\n Explicit Policy Required: "); 553 sb.append(explicitPolicyRequired); 554 sb.append("\n Policy Mapping Inhibited: "); 555 sb.append(policyMappingInhibited); 556 sb.append("\n Any Policy Inhibited: "); 557 sb.append(anyPolicyInhibited); 558 sb.append("\n Policy Qualifiers Rejected: "); 559 sb.append(policyQualifiersRejected); 560 sb.append("\n Initial Policy OIDs: "); 561 sb.append((initialPolicies == null || initialPolicies.isEmpty()) 562 ? "any" : initialPolicies.toString()); 563 sb.append("\n Cert Stores: "); 564 sb.append((certStores==null||certStores.isEmpty())? 565 "no":certStores.toString()); 566 sb.append("\n Validity Date: "); 567 sb.append(date); 568 sb.append("\n Cert Path Checkers: "); 569 sb.append((certPathCheckers==null||certPathCheckers.isEmpty())? 570 "no":certPathCheckers.toString()); 571 sb.append("\n Signature Provider: "); 572 sb.append(sigProvider); 573 sb.append("\n Target Certificate Constraints: "); 574 sb.append(targetCertConstraints); 575 sb.append("\n]"); 576 return sb.toString(); 577 } 578 579 /** 580 * Checks that {@code trustAnchors} contains only {@code 581 * TrustAnchor} instances. 582 * 583 * @throws InvalidAlgorithmParameterException if trustAnchors set is empty. 584 */ 585 private void checkTrustAnchors(Set<TrustAnchor> trustAnchors) 586 throws InvalidAlgorithmParameterException { 587 if (trustAnchors.isEmpty()) { 588 throw new InvalidAlgorithmParameterException("trustAnchors.isEmpty()"); 589 } 590 } 591} 592