1 package org.bouncycastle.x509; 2 3 import java.io.ByteArrayInputStream; 4 import java.io.ByteArrayOutputStream; 5 import java.io.IOException; 6 import java.math.BigInteger; 7 import java.security.GeneralSecurityException; 8 import java.security.KeyFactory; 9 import java.security.PublicKey; 10 import java.security.cert.CRLException; 11 import java.security.cert.CertPathValidatorException; 12 import java.security.cert.CertStore; 13 import java.security.cert.CertStoreException; 14 import java.security.cert.Certificate; 15 import java.security.cert.CertificateException; 16 import java.security.cert.PKIXParameters; 17 import java.security.cert.PolicyQualifierInfo; 18 import java.security.cert.X509CRL; 19 import java.security.cert.X509CRLEntry; 20 import java.security.cert.X509Certificate; 21 import java.security.interfaces.DSAParams; 22 import java.security.interfaces.DSAPublicKey; 23 import java.security.spec.DSAPublicKeySpec; 24 import java.util.ArrayList; 25 import java.util.Collection; 26 import java.util.Date; 27 import java.util.Enumeration; 28 import java.util.HashSet; 29 import java.util.Iterator; 30 import java.util.List; 31 import java.util.Map; 32 import java.util.Set; 33 34 import javax.security.auth.x500.X500Principal; 35 36 import org.bouncycastle.asn1.ASN1Encodable; 37 import org.bouncycastle.asn1.ASN1Enumerated; 38 import org.bouncycastle.asn1.ASN1InputStream; 39 import org.bouncycastle.asn1.ASN1ObjectIdentifier; 40 import org.bouncycastle.asn1.ASN1OctetString; 41 import org.bouncycastle.asn1.ASN1OutputStream; 42 import org.bouncycastle.asn1.ASN1Primitive; 43 import org.bouncycastle.asn1.ASN1Sequence; 44 import org.bouncycastle.asn1.DERSequence; 45 import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 46 import org.bouncycastle.asn1.x509.CRLReason; 47 import org.bouncycastle.asn1.x509.Extension; 48 import org.bouncycastle.asn1.x509.IssuingDistributionPoint; 49 import org.bouncycastle.asn1.x509.PolicyInformation; 50 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 51 import org.bouncycastle.asn1.x509.X509Extension; 52 import org.bouncycastle.jcajce.PKIXCertStoreSelector; 53 import org.bouncycastle.jce.exception.ExtCertPathValidatorException; 54 import org.bouncycastle.jce.provider.AnnotatedException; 55 import org.bouncycastle.jce.provider.BouncyCastleProvider; 56 import org.bouncycastle.jce.provider.PKIXPolicyNode; 57 import org.bouncycastle.util.Encodable; 58 import org.bouncycastle.util.Selector; 59 import org.bouncycastle.util.Store; 60 import org.bouncycastle.util.StoreException; 61 62 class CertPathValidatorUtilities 63 { 64 protected static final String CERTIFICATE_POLICIES = Extension.certificatePolicies.getId(); 65 protected static final String BASIC_CONSTRAINTS = Extension.basicConstraints.getId(); 66 protected static final String POLICY_MAPPINGS = Extension.policyMappings.getId(); 67 protected static final String SUBJECT_ALTERNATIVE_NAME = Extension.subjectAlternativeName.getId(); 68 protected static final String NAME_CONSTRAINTS = Extension.nameConstraints.getId(); 69 protected static final String KEY_USAGE = Extension.keyUsage.getId(); 70 protected static final String INHIBIT_ANY_POLICY = Extension.inhibitAnyPolicy.getId(); 71 protected static final String ISSUING_DISTRIBUTION_POINT = Extension.issuingDistributionPoint.getId(); 72 protected static final String DELTA_CRL_INDICATOR = Extension.deltaCRLIndicator.getId(); 73 protected static final String POLICY_CONSTRAINTS = Extension.policyConstraints.getId(); 74 // protected static final String FRESHEST_CRL = Extension.freshestCRL.getId(); 75 // protected static final String CRL_DISTRIBUTION_POINTS = Extension.cRLDistributionPoints.getId(); 76 // protected static final String AUTHORITY_KEY_IDENTIFIER = Extension.authorityKeyIdentifier.getId(); 77 protected static final String CRL_NUMBER = Extension.cRLNumber.getId(); 78 79 protected static final String ANY_POLICY = "2.5.29.32.0"; 80 81 /* 82 * key usage bits 83 */ 84 protected static final int KEY_CERT_SIGN = 5; 85 protected static final int CRL_SIGN = 6; 86 87 protected static final String[] crlReasons = new String[]{ 88 "unspecified", 89 "keyCompromise", 90 "cACompromise", 91 "affiliationChanged", 92 "superseded", 93 "cessationOfOperation", 94 "certificateHold", 95 "unknown", 96 "removeFromCRL", 97 "privilegeWithdrawn", 98 "aACompromise"}; 99 100 /** 101 * Returns the issuer of an attribute certificate or certificate. 102 * 103 * @param cert The attribute certificate or certificate. 104 * @return The issuer as <code>X500Principal</code>. 105 */ getEncodedIssuerPrincipal( Object cert)106 protected static X500Principal getEncodedIssuerPrincipal( 107 Object cert) 108 { 109 if (cert instanceof X509Certificate) 110 { 111 return ((X509Certificate)cert).getIssuerX500Principal(); 112 } 113 else 114 { 115 return (X500Principal)((X509AttributeCertificate)cert).getIssuer().getPrincipals()[0]; 116 } 117 } 118 getValidityDate(PKIXParameters paramsPKIX, Date currentDate)119 protected static Date getValidityDate(PKIXParameters paramsPKIX, Date currentDate) 120 { 121 Date validityDate = paramsPKIX.getDate(); 122 123 return null == validityDate ? currentDate : validityDate; 124 } 125 getSubjectPrincipal(X509Certificate cert)126 protected static X500Principal getSubjectPrincipal(X509Certificate cert) 127 { 128 return cert.getSubjectX500Principal(); 129 } 130 isSelfIssued(X509Certificate cert)131 protected static boolean isSelfIssued(X509Certificate cert) 132 { 133 return cert.getSubjectDN().equals(cert.getIssuerDN()); 134 } 135 136 137 /** 138 * Extract the value of the given extension, if it exists. 139 * 140 * @param ext The extension object. 141 * @param oid The object identifier to obtain. 142 * @throws AnnotatedException if the extension cannot be read. 143 */ getExtensionValue( java.security.cert.X509Extension ext, String oid)144 protected static ASN1Primitive getExtensionValue( 145 java.security.cert.X509Extension ext, 146 String oid) 147 throws AnnotatedException 148 { 149 byte[] bytes = ext.getExtensionValue(oid); 150 if (bytes == null) 151 { 152 return null; 153 } 154 155 return getObject(oid, bytes); 156 } 157 getObject( String oid, byte[] ext)158 private static ASN1Primitive getObject( 159 String oid, 160 byte[] ext) 161 throws AnnotatedException 162 { 163 try 164 { 165 ASN1InputStream aIn = new ASN1InputStream(ext); 166 ASN1OctetString octs = (ASN1OctetString)aIn.readObject(); 167 168 aIn = new ASN1InputStream(octs.getOctets()); 169 return aIn.readObject(); 170 } 171 catch (Exception e) 172 { 173 throw new AnnotatedException("exception processing extension " + oid, e); 174 } 175 } 176 getIssuerPrincipal(X509CRL crl)177 protected static X500Principal getIssuerPrincipal(X509CRL crl) 178 { 179 return crl.getIssuerX500Principal(); 180 } 181 getAlgorithmIdentifier( PublicKey key)182 protected static AlgorithmIdentifier getAlgorithmIdentifier( 183 PublicKey key) 184 throws CertPathValidatorException 185 { 186 try 187 { 188 ASN1InputStream aIn = new ASN1InputStream(key.getEncoded()); 189 190 SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(aIn.readObject()); 191 192 return info.getAlgorithmId(); 193 } 194 catch (Exception e) 195 { 196 throw new ExtCertPathValidatorException("Subject public key cannot be decoded.", e); 197 } 198 } 199 200 // crl checking 201 202 203 // 204 // policy checking 205 // 206 getQualifierSet(ASN1Sequence qualifiers)207 protected static final Set getQualifierSet(ASN1Sequence qualifiers) 208 throws CertPathValidatorException 209 { 210 Set pq = new HashSet(); 211 212 if (qualifiers == null) 213 { 214 return pq; 215 } 216 217 ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 218 ASN1OutputStream aOut = ASN1OutputStream.create(bOut); 219 220 Enumeration e = qualifiers.getObjects(); 221 222 while (e.hasMoreElements()) 223 { 224 try 225 { 226 aOut.writeObject((ASN1Encodable)e.nextElement()); 227 228 pq.add(new PolicyQualifierInfo(bOut.toByteArray())); 229 } 230 catch (IOException ex) 231 { 232 throw new ExtCertPathValidatorException("Policy qualifier info cannot be decoded.", ex); 233 } 234 235 bOut.reset(); 236 } 237 238 return pq; 239 } 240 removePolicyNode( PKIXPolicyNode validPolicyTree, List[] policyNodes, PKIXPolicyNode _node)241 protected static PKIXPolicyNode removePolicyNode( 242 PKIXPolicyNode validPolicyTree, 243 List[] policyNodes, 244 PKIXPolicyNode _node) 245 { 246 PKIXPolicyNode _parent = (PKIXPolicyNode)_node.getParent(); 247 248 if (validPolicyTree == null) 249 { 250 return null; 251 } 252 253 if (_parent == null) 254 { 255 for (int j = 0; j < policyNodes.length; j++) 256 { 257 policyNodes[j] = new ArrayList(); 258 } 259 260 return null; 261 } 262 else 263 { 264 _parent.removeChild(_node); 265 removePolicyNodeRecurse(policyNodes, _node); 266 267 return validPolicyTree; 268 } 269 } 270 removePolicyNodeRecurse( List[] policyNodes, PKIXPolicyNode _node)271 private static void removePolicyNodeRecurse( 272 List[] policyNodes, 273 PKIXPolicyNode _node) 274 { 275 policyNodes[_node.getDepth()].remove(_node); 276 277 if (_node.hasChildren()) 278 { 279 Iterator _iter = _node.getChildren(); 280 while (_iter.hasNext()) 281 { 282 PKIXPolicyNode _child = (PKIXPolicyNode)_iter.next(); 283 removePolicyNodeRecurse(policyNodes, _child); 284 } 285 } 286 } 287 288 processCertD1i( int index, List[] policyNodes, ASN1ObjectIdentifier pOid, Set pq)289 protected static boolean processCertD1i( 290 int index, 291 List[] policyNodes, 292 ASN1ObjectIdentifier pOid, 293 Set pq) 294 { 295 List policyNodeVec = policyNodes[index - 1]; 296 297 for (int j = 0; j < policyNodeVec.size(); j++) 298 { 299 PKIXPolicyNode node = (PKIXPolicyNode)policyNodeVec.get(j); 300 Set expectedPolicies = node.getExpectedPolicies(); 301 302 if (expectedPolicies.contains(pOid.getId())) 303 { 304 Set childExpectedPolicies = new HashSet(); 305 childExpectedPolicies.add(pOid.getId()); 306 307 PKIXPolicyNode child = new PKIXPolicyNode(new ArrayList(), 308 index, 309 childExpectedPolicies, 310 node, 311 pq, 312 pOid.getId(), 313 false); 314 node.addChild(child); 315 policyNodes[index].add(child); 316 317 return true; 318 } 319 } 320 321 return false; 322 } 323 processCertD1ii( int index, List[] policyNodes, ASN1ObjectIdentifier _poid, Set _pq)324 protected static void processCertD1ii( 325 int index, 326 List[] policyNodes, 327 ASN1ObjectIdentifier _poid, 328 Set _pq) 329 { 330 List policyNodeVec = policyNodes[index - 1]; 331 332 for (int j = 0; j < policyNodeVec.size(); j++) 333 { 334 PKIXPolicyNode _node = (PKIXPolicyNode)policyNodeVec.get(j); 335 336 if (ANY_POLICY.equals(_node.getValidPolicy())) 337 { 338 Set _childExpectedPolicies = new HashSet(); 339 _childExpectedPolicies.add(_poid.getId()); 340 341 PKIXPolicyNode _child = new PKIXPolicyNode(new ArrayList(), 342 index, 343 _childExpectedPolicies, 344 _node, 345 _pq, 346 _poid.getId(), 347 false); 348 _node.addChild(_child); 349 policyNodes[index].add(_child); 350 return; 351 } 352 } 353 } 354 prepareNextCertB1( int i, List[] policyNodes, String id_p, Map m_idp, X509Certificate cert )355 protected static void prepareNextCertB1( 356 int i, 357 List[] policyNodes, 358 String id_p, 359 Map m_idp, 360 X509Certificate cert 361 ) 362 throws AnnotatedException, CertPathValidatorException 363 { 364 boolean idp_found = false; 365 Iterator nodes_i = policyNodes[i].iterator(); 366 while (nodes_i.hasNext()) 367 { 368 PKIXPolicyNode node = (PKIXPolicyNode)nodes_i.next(); 369 if (node.getValidPolicy().equals(id_p)) 370 { 371 idp_found = true; 372 node.setExpectedPolicies((Set)m_idp.get(id_p)); 373 break; 374 } 375 } 376 377 if (!idp_found) 378 { 379 nodes_i = policyNodes[i].iterator(); 380 while (nodes_i.hasNext()) 381 { 382 PKIXPolicyNode node = (PKIXPolicyNode)nodes_i.next(); 383 if (ANY_POLICY.equals(node.getValidPolicy())) 384 { 385 Set pq = null; 386 ASN1Sequence policies = null; 387 try 388 { 389 policies = DERSequence.getInstance(getExtensionValue(cert, CERTIFICATE_POLICIES)); 390 } 391 catch (Exception e) 392 { 393 throw new AnnotatedException("Certificate policies cannot be decoded.", e); 394 } 395 Enumeration e = policies.getObjects(); 396 while (e.hasMoreElements()) 397 { 398 PolicyInformation pinfo = null; 399 400 try 401 { 402 pinfo = PolicyInformation.getInstance(e.nextElement()); 403 } 404 catch (Exception ex) 405 { 406 throw new AnnotatedException("Policy information cannot be decoded.", ex); 407 } 408 if (ANY_POLICY.equals(pinfo.getPolicyIdentifier().getId())) 409 { 410 try 411 { 412 pq = getQualifierSet(pinfo.getPolicyQualifiers()); 413 } 414 catch (CertPathValidatorException ex) 415 { 416 throw new ExtCertPathValidatorException( 417 "Policy qualifier info set could not be built.", ex); 418 } 419 break; 420 } 421 } 422 boolean ci = false; 423 if (cert.getCriticalExtensionOIDs() != null) 424 { 425 ci = cert.getCriticalExtensionOIDs().contains(CERTIFICATE_POLICIES); 426 } 427 428 PKIXPolicyNode p_node = (PKIXPolicyNode)node.getParent(); 429 if (ANY_POLICY.equals(p_node.getValidPolicy())) 430 { 431 PKIXPolicyNode c_node = new PKIXPolicyNode( 432 new ArrayList(), i, 433 (Set)m_idp.get(id_p), 434 p_node, pq, id_p, ci); 435 p_node.addChild(c_node); 436 policyNodes[i].add(c_node); 437 } 438 break; 439 } 440 } 441 } 442 } 443 prepareNextCertB2( int i, List[] policyNodes, String id_p, PKIXPolicyNode validPolicyTree)444 protected static PKIXPolicyNode prepareNextCertB2( 445 int i, 446 List[] policyNodes, 447 String id_p, 448 PKIXPolicyNode validPolicyTree) 449 { 450 Iterator nodes_i = policyNodes[i].iterator(); 451 while (nodes_i.hasNext()) 452 { 453 PKIXPolicyNode node = (PKIXPolicyNode)nodes_i.next(); 454 if (node.getValidPolicy().equals(id_p)) 455 { 456 PKIXPolicyNode p_node = (PKIXPolicyNode)node.getParent(); 457 p_node.removeChild(node); 458 nodes_i.remove(); 459 for (int k = (i - 1); k >= 0; k--) 460 { 461 List nodes = policyNodes[k]; 462 for (int l = 0; l < nodes.size(); l++) 463 { 464 PKIXPolicyNode node2 = (PKIXPolicyNode)nodes.get(l); 465 if (!node2.hasChildren()) 466 { 467 validPolicyTree = removePolicyNode(validPolicyTree, policyNodes, node2); 468 if (validPolicyTree == null) 469 { 470 break; 471 } 472 } 473 } 474 } 475 } 476 } 477 return validPolicyTree; 478 } 479 isAnyPolicy( Set policySet)480 protected static boolean isAnyPolicy( 481 Set policySet) 482 { 483 return policySet == null || policySet.contains(ANY_POLICY) || policySet.isEmpty(); 484 } 485 486 /** 487 * Return a Collection of all certificates or attribute certificates found 488 * in the X509Store's that are matching the certSelect criteriums. 489 * 490 * @param certSelect a {@link Selector} object that will be used to select 491 * the certificates 492 * @param certStores a List containing only {@link X509Store} objects. These 493 * are used to search for certificates. 494 * @return a Collection of all found {@link X509Certificate} or 495 * {@link org.bouncycastle.x509.X509AttributeCertificate} objects. 496 * May be empty but never <code>null</code>. 497 */ findCertificates(X509CertStoreSelector certSelect, List certStores)498 protected static Collection findCertificates(X509CertStoreSelector certSelect, 499 List certStores) 500 throws AnnotatedException 501 { 502 Set certs = new HashSet(); 503 Iterator iter = certStores.iterator(); 504 org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory certFact = new org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory(); 505 506 while (iter.hasNext()) 507 { 508 Object obj = iter.next(); 509 510 if (obj instanceof Store) 511 { 512 Store certStore = (Store)obj; 513 try 514 { 515 for (Iterator it = certStore.getMatches(certSelect).iterator(); it.hasNext();) 516 { 517 Object cert = it.next(); 518 519 if (cert instanceof Encodable) 520 { 521 certs.add(certFact.engineGenerateCertificate(new ByteArrayInputStream(((Encodable)cert).getEncoded()))); 522 } 523 else if (cert instanceof Certificate) 524 { 525 certs.add(cert); 526 } 527 else 528 { 529 throw new AnnotatedException( 530 "Unknown object found in certificate store."); 531 } 532 } 533 } 534 catch (StoreException e) 535 { 536 throw new AnnotatedException( 537 "Problem while picking certificates from X.509 store.", e); 538 } 539 catch (IOException e) 540 { 541 throw new AnnotatedException( 542 "Problem while extracting certificates from X.509 store.", e); 543 } 544 catch (CertificateException e) 545 { 546 throw new AnnotatedException( 547 "Problem while extracting certificates from X.509 store.", e); 548 } 549 } 550 else 551 { 552 CertStore certStore = (CertStore)obj; 553 554 try 555 { 556 certs.addAll(certStore.getCertificates(certSelect)); 557 } 558 catch (CertStoreException e) 559 { 560 throw new AnnotatedException( 561 "Problem while picking certificates from certificate store.", 562 e); 563 } 564 } 565 } 566 return certs; 567 } 568 findCertificates(PKIXCertStoreSelector certSelect, List certStores)569 protected static Collection findCertificates(PKIXCertStoreSelector certSelect, 570 List certStores) 571 throws AnnotatedException 572 { 573 Set certs = new HashSet(); 574 Iterator iter = certStores.iterator(); 575 576 while (iter.hasNext()) 577 { 578 Object obj = iter.next(); 579 580 if (obj instanceof Store) 581 { 582 Store certStore = (Store)obj; 583 try 584 { 585 certs.addAll(certStore.getMatches(certSelect)); 586 } 587 catch (StoreException e) 588 { 589 throw new AnnotatedException( 590 "Problem while picking certificates from X.509 store.", e); 591 } 592 } 593 else 594 { 595 CertStore certStore = (CertStore)obj; 596 597 try 598 { 599 certs.addAll(PKIXCertStoreSelector.getCertificates(certSelect, certStore)); 600 } 601 catch (CertStoreException e) 602 { 603 throw new AnnotatedException( 604 "Problem while picking certificates from certificate store.", 605 e); 606 } 607 } 608 } 609 return certs; 610 } 611 findCertificates(X509AttributeCertStoreSelector certSelect, List certStores)612 protected static Collection findCertificates(X509AttributeCertStoreSelector certSelect, 613 List certStores) 614 throws AnnotatedException 615 { 616 Set certs = new HashSet(); 617 Iterator iter = certStores.iterator(); 618 619 while (iter.hasNext()) 620 { 621 Object obj = iter.next(); 622 623 if (obj instanceof X509Store) 624 { 625 X509Store certStore = (X509Store)obj; 626 try 627 { 628 certs.addAll(certStore.getMatches(certSelect)); 629 } 630 catch (StoreException e) 631 { 632 throw new AnnotatedException( 633 "Problem while picking certificates from X.509 store.", e); 634 } 635 } 636 } 637 return certs; 638 } 639 getSerialNumber( Object cert)640 private static BigInteger getSerialNumber( 641 Object cert) 642 { 643 if (cert instanceof X509Certificate) 644 { 645 return ((X509Certificate)cert).getSerialNumber(); 646 } 647 else 648 { 649 return ((X509AttributeCertificate)cert).getSerialNumber(); 650 } 651 } 652 getCertStatus( Date validDate, X509CRL crl, Object cert, CertStatus certStatus)653 protected static void getCertStatus( 654 Date validDate, 655 X509CRL crl, 656 Object cert, 657 CertStatus certStatus) 658 throws AnnotatedException 659 { 660 X509CRLEntry crl_entry = null; 661 662 boolean isIndirect; 663 try 664 { 665 isIndirect = isIndirectCRL(crl); 666 } 667 catch (CRLException exception) 668 { 669 throw new AnnotatedException("Failed check for indirect CRL.", exception); 670 } 671 672 if (isIndirect) 673 { 674 crl_entry = crl.getRevokedCertificate(getSerialNumber(cert)); 675 676 if (crl_entry == null) 677 { 678 return; 679 } 680 681 X500Principal certIssuer = crl_entry.getCertificateIssuer(); 682 683 if (certIssuer == null) 684 { 685 certIssuer = getIssuerPrincipal(crl); 686 } 687 688 if (!getEncodedIssuerPrincipal(cert).equals(certIssuer)) 689 { 690 return; 691 } 692 } 693 else if (!getEncodedIssuerPrincipal(cert).equals(getIssuerPrincipal(crl))) 694 { 695 return; // not for our issuer, ignore 696 } 697 else 698 { 699 crl_entry = crl.getRevokedCertificate(getSerialNumber(cert)); 700 701 if (crl_entry == null) 702 { 703 return; 704 } 705 } 706 707 ASN1Enumerated reasonCode = null; 708 if (crl_entry.hasExtensions()) 709 { 710 try 711 { 712 reasonCode = ASN1Enumerated 713 .getInstance(CertPathValidatorUtilities 714 .getExtensionValue(crl_entry, 715 X509Extension.reasonCode.getId())); 716 } 717 catch (Exception e) 718 { 719 throw new AnnotatedException( 720 "Reason code CRL entry extension could not be decoded.", 721 e); 722 } 723 } 724 725 int reasonCodeValue = (null == reasonCode) 726 ? CRLReason.unspecified 727 : reasonCode.intValueExact(); 728 729 // for reason keyCompromise, caCompromise, aACompromise or unspecified 730 if (!(validDate.getTime() < crl_entry.getRevocationDate().getTime()) 731 || reasonCodeValue == CRLReason.unspecified 732 || reasonCodeValue == CRLReason.keyCompromise 733 || reasonCodeValue == CRLReason.cACompromise 734 || reasonCodeValue == CRLReason.aACompromise) 735 { 736 // (i) or (j) 737 certStatus.setCertStatus(reasonCodeValue); 738 certStatus.setRevocationDate(crl_entry.getRevocationDate()); 739 } 740 } 741 742 /** 743 * Return the next working key inheriting DSA parameters if necessary. 744 * <p> 745 * This methods inherits DSA parameters from the indexed certificate or 746 * previous certificates in the certificate chain to the returned 747 * <code>PublicKey</code>. The list is searched upwards, meaning the end 748 * certificate is at position 0 and previous certificates are following. 749 * </p> 750 * <p> 751 * If the indexed certificate does not contain a DSA key this method simply 752 * returns the public key. If the DSA key already contains DSA parameters 753 * the key is also only returned. 754 * </p> 755 * 756 * @param certs The certification path. 757 * @param index The index of the certificate which contains the public key 758 * which should be extended with DSA parameters. 759 * @return The public key of the certificate in list position 760 * <code>index</code> extended with DSA parameters if applicable. 761 * @throws CertPathValidatorException if DSA parameters cannot be inherited. 762 */ getNextWorkingKey(List certs, int index)763 protected static PublicKey getNextWorkingKey(List certs, int index) 764 throws CertPathValidatorException 765 { 766 Certificate cert = (Certificate)certs.get(index); 767 PublicKey pubKey = cert.getPublicKey(); 768 if (!(pubKey instanceof DSAPublicKey)) 769 { 770 return pubKey; 771 } 772 DSAPublicKey dsaPubKey = (DSAPublicKey)pubKey; 773 if (dsaPubKey.getParams() != null) 774 { 775 return dsaPubKey; 776 } 777 for (int i = index + 1; i < certs.size(); i++) 778 { 779 X509Certificate parentCert = (X509Certificate)certs.get(i); 780 pubKey = parentCert.getPublicKey(); 781 if (!(pubKey instanceof DSAPublicKey)) 782 { 783 throw new CertPathValidatorException( 784 "DSA parameters cannot be inherited from previous certificate."); 785 } 786 DSAPublicKey prevDSAPubKey = (DSAPublicKey)pubKey; 787 if (prevDSAPubKey.getParams() == null) 788 { 789 continue; 790 } 791 DSAParams dsaParams = prevDSAPubKey.getParams(); 792 DSAPublicKeySpec dsaPubKeySpec = new DSAPublicKeySpec( 793 dsaPubKey.getY(), dsaParams.getP(), dsaParams.getQ(), dsaParams.getG()); 794 try 795 { 796 KeyFactory keyFactory = KeyFactory.getInstance("DSA", BouncyCastleProvider.PROVIDER_NAME); 797 return keyFactory.generatePublic(dsaPubKeySpec); 798 } 799 catch (Exception exception) 800 { 801 throw new RuntimeException(exception.getMessage()); 802 } 803 } 804 throw new CertPathValidatorException("DSA parameters cannot be inherited from previous certificate."); 805 } 806 verifyX509Certificate(X509Certificate cert, PublicKey publicKey, String sigProvider)807 protected static void verifyX509Certificate(X509Certificate cert, PublicKey publicKey, 808 String sigProvider) 809 throws GeneralSecurityException 810 { 811 if (sigProvider == null) 812 { 813 cert.verify(publicKey); 814 } 815 else 816 { 817 cert.verify(publicKey, sigProvider); 818 } 819 } 820 isIndirectCRL(X509CRL crl)821 static boolean isIndirectCRL(X509CRL crl) 822 throws CRLException 823 { 824 try 825 { 826 byte[] idp = crl.getExtensionValue(Extension.issuingDistributionPoint.getId()); 827 return idp != null 828 && IssuingDistributionPoint.getInstance(ASN1OctetString.getInstance(idp).getOctets()).isIndirectCRL(); 829 } 830 catch (Exception e) 831 { 832 throw new CRLException( 833 "Exception reading IssuingDistributionPoint: " + e); 834 } 835 } 836 } 837