1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 package sun.security.pkcs; 28 29 import java.io.*; 30 import java.math.BigInteger; 31 import java.util.*; 32 import java.security.cert.X509Certificate; 33 import java.security.cert.CertificateException; 34 import java.security.cert.CertificateEncodingException; 35 import java.security.cert.CertificateExpiredException; 36 import java.security.cert.CertificateNotYetValidException; 37 import java.security.cert.CertificateParsingException; 38 import java.security.cert.X509CRL; 39 import java.security.cert.CRLException; 40 import java.security.cert.CertificateFactory; 41 import java.security.*; 42 43 import javax.security.auth.x500.X500Principal; 44 45 import sun.security.util.*; 46 import sun.security.x509.AlgorithmId; 47 import sun.security.x509.CertificateIssuerName; 48 import sun.security.x509.X509CertImpl; 49 import sun.security.x509.X509CertInfo; 50 import sun.security.x509.X509CRLImpl; 51 import sun.security.x509.X500Name; 52 53 /** 54 * PKCS7 as defined in RSA Laboratories PKCS7 Technical Note. Profile 55 * Supports only <tt>SignedData</tt> ContentInfo 56 * type, where to the type of data signed is plain Data. 57 * For signedData, <tt>crls</tt>, <tt>attributes</tt> and 58 * PKCS#6 Extended Certificates are not supported. 59 * 60 * @author Benjamin Renaud 61 */ 62 public class PKCS7 { 63 64 private ObjectIdentifier contentType; 65 66 // the ASN.1 members for a signedData (and other) contentTypes 67 private BigInteger version = null; 68 private AlgorithmId[] digestAlgorithmIds = null; 69 private ContentInfo contentInfo = null; 70 private X509Certificate[] certificates = null; 71 private X509CRL[] crls = null; 72 private SignerInfo[] signerInfos = null; 73 74 private boolean oldStyle = false; // Is this JDK1.1.x-style? 75 76 private Principal[] certIssuerNames; 77 78 /** 79 * Unmarshals a PKCS7 block from its encoded form, parsing the 80 * encoded bytes from the InputStream. 81 * 82 * @param in an input stream holding at least one PKCS7 block. 83 * @exception ParsingException on parsing errors. 84 * @exception IOException on other errors. 85 */ 86 public PKCS7(InputStream in) throws ParsingException, IOException { 87 DataInputStream dis = new DataInputStream(in); 88 byte[] data = new byte[dis.available()]; 89 dis.readFully(data); 90 91 parse(new DerInputStream(data)); 92 } 93 94 /** 95 * Unmarshals a PKCS7 block from its encoded form, parsing the 96 * encoded bytes from the DerInputStream. 97 * 98 * @param derin a DerInputStream holding at least one PKCS7 block. 99 * @exception ParsingException on parsing errors. 100 */ 101 public PKCS7(DerInputStream derin) throws ParsingException { 102 parse(derin); 103 } 104 105 /** 106 * Unmarshals a PKCS7 block from its encoded form, parsing the 107 * encoded bytes. 108 * 109 * @param bytes the encoded bytes. 110 * @exception ParsingException on parsing errors. 111 */ 112 public PKCS7(byte[] bytes) throws ParsingException { 113 try { 114 DerInputStream derin = new DerInputStream(bytes); 115 parse(derin); 116 } catch (IOException ioe1) { 117 ParsingException pe = new ParsingException( 118 "Unable to parse the encoded bytes"); 119 pe.initCause(ioe1); 120 throw pe; 121 } 122 } 123 124 /* 125 * Parses a PKCS#7 block. 126 */ 127 private void parse(DerInputStream derin) 128 throws ParsingException 129 { 130 try { 131 derin.mark(derin.available()); 132 // try new (i.e., JDK1.2) style 133 parse(derin, false); 134 } catch (IOException ioe) { 135 try { 136 derin.reset(); 137 // try old (i.e., JDK1.1.x) style 138 parse(derin, true); 139 oldStyle = true; 140 } catch (IOException ioe1) { 141 ParsingException pe = new ParsingException( 142 ioe1.getMessage()); 143 pe.initCause(ioe); 144 pe.addSuppressed(ioe1); 145 throw pe; 146 } 147 } 148 } 149 150 /** 151 * Parses a PKCS#7 block. 152 * 153 * @param derin the ASN.1 encoding of the PKCS#7 block. 154 * @param oldStyle flag indicating whether or not the given PKCS#7 block 155 * is encoded according to JDK1.1.x. 156 */ 157 private void parse(DerInputStream derin, boolean oldStyle) 158 throws IOException 159 { 160 contentInfo = new ContentInfo(derin, oldStyle); 161 contentType = contentInfo.contentType; 162 DerValue content = contentInfo.getContent(); 163 164 if (contentType.equals(ContentInfo.SIGNED_DATA_OID)) { 165 parseSignedData(content); 166 } else if (contentType.equals(ContentInfo.OLD_SIGNED_DATA_OID)) { 167 // This is for backwards compatibility with JDK 1.1.x 168 parseOldSignedData(content); 169 } else if (contentType.equals(ContentInfo.NETSCAPE_CERT_SEQUENCE_OID)){ 170 parseNetscapeCertChain(content); 171 } else { 172 throw new ParsingException("content type " + contentType + 173 " not supported."); 174 } 175 } 176 177 /** 178 * Construct an initialized PKCS7 block. 179 * 180 * @param digestAlgorithmIds the message digest algorithm identifiers. 181 * @param contentInfo the content information. 182 * @param certificates an array of X.509 certificates. 183 * @param crls an array of CRLs 184 * @param signerInfos an array of signer information. 185 */ 186 public PKCS7(AlgorithmId[] digestAlgorithmIds, 187 ContentInfo contentInfo, 188 X509Certificate[] certificates, 189 X509CRL[] crls, 190 SignerInfo[] signerInfos) { 191 192 version = BigInteger.ONE; 193 this.digestAlgorithmIds = digestAlgorithmIds; 194 this.contentInfo = contentInfo; 195 this.certificates = certificates; 196 this.crls = crls; 197 this.signerInfos = signerInfos; 198 } 199 200 public PKCS7(AlgorithmId[] digestAlgorithmIds, 201 ContentInfo contentInfo, 202 X509Certificate[] certificates, 203 SignerInfo[] signerInfos) { 204 this(digestAlgorithmIds, contentInfo, certificates, null, signerInfos); 205 } 206 207 private void parseNetscapeCertChain(DerValue val) 208 throws ParsingException, IOException { 209 DerInputStream dis = new DerInputStream(val.toByteArray()); 210 DerValue[] contents = dis.getSequence(2, true); 211 certificates = new X509Certificate[contents.length]; 212 213 CertificateFactory certfac = null; 214 try { 215 certfac = CertificateFactory.getInstance("X.509"); 216 } catch (CertificateException ce) { 217 // do nothing 218 } 219 220 for (int i=0; i < contents.length; i++) { 221 ByteArrayInputStream bais = null; 222 try { 223 byte[] original = contents[i].getOriginalEncodedForm(); 224 if (certfac == null) 225 certificates[i] = new X509CertImpl(contents[i], original); 226 else { 227 bais = new ByteArrayInputStream(original); 228 certificates[i] = new VerbatimX509Certificate( 229 (X509Certificate)certfac.generateCertificate(bais), 230 original); 231 bais.close(); 232 bais = null; 233 } 234 } catch (CertificateException ce) { 235 ParsingException pe = new ParsingException(ce.getMessage()); 236 pe.initCause(ce); 237 throw pe; 238 } catch (IOException ioe) { 239 ParsingException pe = new ParsingException(ioe.getMessage()); 240 pe.initCause(ioe); 241 throw pe; 242 } finally { 243 if (bais != null) 244 bais.close(); 245 } 246 } 247 } 248 249 private void parseSignedData(DerValue val) 250 throws ParsingException, IOException { 251 252 DerInputStream dis = val.toDerInputStream(); 253 254 // Version 255 version = dis.getBigInteger(); 256 257 // digestAlgorithmIds 258 DerValue[] digestAlgorithmIdVals = dis.getSet(1); 259 int len = digestAlgorithmIdVals.length; 260 digestAlgorithmIds = new AlgorithmId[len]; 261 try { 262 for (int i = 0; i < len; i++) { 263 DerValue oid = digestAlgorithmIdVals[i]; 264 digestAlgorithmIds[i] = AlgorithmId.parse(oid); 265 } 266 267 } catch (IOException e) { 268 ParsingException pe = 269 new ParsingException("Error parsing digest AlgorithmId IDs: " + 270 e.getMessage()); 271 pe.initCause(e); 272 throw pe; 273 } 274 // contentInfo 275 contentInfo = new ContentInfo(dis); 276 277 CertificateFactory certfac = null; 278 try { 279 certfac = CertificateFactory.getInstance("X.509"); 280 } catch (CertificateException ce) { 281 // do nothing 282 } 283 284 /* 285 * check if certificates (implicit tag) are provided 286 * (certificates are OPTIONAL) 287 */ 288 if ((byte)(dis.peekByte()) == (byte)0xA0) { 289 DerValue[] certVals = dis.getSet(2, true, true); 290 291 len = certVals.length; 292 certificates = new X509Certificate[len]; 293 int count = 0; 294 295 for (int i = 0; i < len; i++) { 296 ByteArrayInputStream bais = null; 297 try { 298 byte tag = certVals[i].getTag(); 299 // We only parse the normal certificate. Other types of 300 // CertificateChoices ignored. 301 if (tag == DerValue.tag_Sequence) { 302 byte[] original = certVals[i].getOriginalEncodedForm(); 303 if (certfac == null) { 304 certificates[count] = new X509CertImpl(certVals[i], original); 305 } else { 306 bais = new ByteArrayInputStream(original); 307 certificates[count] = new VerbatimX509Certificate( 308 (X509Certificate)certfac.generateCertificate(bais), 309 original); 310 bais.close(); 311 bais = null; 312 } 313 count++; 314 } 315 } catch (CertificateException ce) { 316 ParsingException pe = new ParsingException(ce.getMessage()); 317 pe.initCause(ce); 318 throw pe; 319 } catch (IOException ioe) { 320 ParsingException pe = new ParsingException(ioe.getMessage()); 321 pe.initCause(ioe); 322 throw pe; 323 } finally { 324 if (bais != null) 325 bais.close(); 326 } 327 } 328 if (count != len) { 329 certificates = Arrays.copyOf(certificates, count); 330 } 331 } 332 333 // check if crls (implicit tag) are provided (crls are OPTIONAL) 334 if ((byte)(dis.peekByte()) == (byte)0xA1) { 335 DerValue[] crlVals = dis.getSet(1, true); 336 337 len = crlVals.length; 338 crls = new X509CRL[len]; 339 340 for (int i = 0; i < len; i++) { 341 ByteArrayInputStream bais = null; 342 try { 343 if (certfac == null) 344 crls[i] = new X509CRLImpl(crlVals[i]); 345 else { 346 byte[] encoded = crlVals[i].toByteArray(); 347 bais = new ByteArrayInputStream(encoded); 348 crls[i] = (X509CRL) certfac.generateCRL(bais); 349 bais.close(); 350 bais = null; 351 } 352 } catch (CRLException e) { 353 ParsingException pe = 354 new ParsingException(e.getMessage()); 355 pe.initCause(e); 356 throw pe; 357 } finally { 358 if (bais != null) 359 bais.close(); 360 } 361 } 362 } 363 364 // signerInfos 365 DerValue[] signerInfoVals = dis.getSet(1); 366 367 len = signerInfoVals.length; 368 signerInfos = new SignerInfo[len]; 369 370 for (int i = 0; i < len; i++) { 371 DerInputStream in = signerInfoVals[i].toDerInputStream(); 372 signerInfos[i] = new SignerInfo(in); 373 } 374 } 375 376 /* 377 * Parses an old-style SignedData encoding (for backwards 378 * compatibility with JDK1.1.x). 379 */ 380 private void parseOldSignedData(DerValue val) 381 throws ParsingException, IOException 382 { 383 DerInputStream dis = val.toDerInputStream(); 384 385 // Version 386 version = dis.getBigInteger(); 387 388 // digestAlgorithmIds 389 DerValue[] digestAlgorithmIdVals = dis.getSet(1); 390 int len = digestAlgorithmIdVals.length; 391 392 digestAlgorithmIds = new AlgorithmId[len]; 393 try { 394 for (int i = 0; i < len; i++) { 395 DerValue oid = digestAlgorithmIdVals[i]; 396 digestAlgorithmIds[i] = AlgorithmId.parse(oid); 397 } 398 } catch (IOException e) { 399 throw new ParsingException("Error parsing digest AlgorithmId IDs"); 400 } 401 402 // contentInfo 403 contentInfo = new ContentInfo(dis, true); 404 405 // certificates 406 CertificateFactory certfac = null; 407 try { 408 certfac = CertificateFactory.getInstance("X.509"); 409 } catch (CertificateException ce) { 410 // do nothing 411 } 412 DerValue[] certVals = dis.getSet(2, false, true); 413 len = certVals.length; 414 certificates = new X509Certificate[len]; 415 416 for (int i = 0; i < len; i++) { 417 ByteArrayInputStream bais = null; 418 try { 419 byte[] original = certVals[i].getOriginalEncodedForm(); 420 if (certfac == null) 421 certificates[i] = new X509CertImpl(certVals[i], original); 422 else { 423 bais = new ByteArrayInputStream(original); 424 certificates[i] = new VerbatimX509Certificate( 425 (X509Certificate)certfac.generateCertificate(bais), 426 original); 427 bais.close(); 428 bais = null; 429 } 430 } catch (CertificateException ce) { 431 ParsingException pe = new ParsingException(ce.getMessage()); 432 pe.initCause(ce); 433 throw pe; 434 } catch (IOException ioe) { 435 ParsingException pe = new ParsingException(ioe.getMessage()); 436 pe.initCause(ioe); 437 throw pe; 438 } finally { 439 if (bais != null) 440 bais.close(); 441 } 442 } 443 444 // crls are ignored. 445 dis.getSet(0); 446 447 // signerInfos 448 DerValue[] signerInfoVals = dis.getSet(1); 449 len = signerInfoVals.length; 450 signerInfos = new SignerInfo[len]; 451 for (int i = 0; i < len; i++) { 452 DerInputStream in = signerInfoVals[i].toDerInputStream(); 453 signerInfos[i] = new SignerInfo(in, true); 454 } 455 } 456 457 /** 458 * Encodes the signed data to an output stream. 459 * 460 * @param out the output stream to write the encoded data to. 461 * @exception IOException on encoding errors. 462 */ 463 public void encodeSignedData(OutputStream out) throws IOException { 464 DerOutputStream derout = new DerOutputStream(); 465 encodeSignedData(derout); 466 out.write(derout.toByteArray()); 467 } 468 469 /** 470 * Encodes the signed data to a DerOutputStream. 471 * 472 * @param out the DerOutputStream to write the encoded data to. 473 * @exception IOException on encoding errors. 474 */ 475 public void encodeSignedData(DerOutputStream out) 476 throws IOException 477 { 478 DerOutputStream signedData = new DerOutputStream(); 479 480 // version 481 signedData.putInteger(version); 482 483 // digestAlgorithmIds 484 signedData.putOrderedSetOf(DerValue.tag_Set, digestAlgorithmIds); 485 486 // contentInfo 487 contentInfo.encode(signedData); 488 489 // certificates (optional) 490 if (certificates != null && certificates.length != 0) { 491 // cast to X509CertImpl[] since X509CertImpl implements DerEncoder 492 X509CertImpl implCerts[] = new X509CertImpl[certificates.length]; 493 for (int i = 0; i < certificates.length; i++) { 494 if (certificates[i] instanceof X509CertImpl) 495 implCerts[i] = (X509CertImpl) certificates[i]; 496 else { 497 try { 498 byte[] encoded = certificates[i].getEncoded(); 499 implCerts[i] = new X509CertImpl(encoded); 500 } catch (CertificateException ce) { 501 IOException ie = new IOException(ce.getMessage()); 502 ie.initCause(ce); 503 throw ie; 504 } 505 } 506 } 507 508 // Add the certificate set (tagged with [0] IMPLICIT) 509 // to the signed data 510 signedData.putOrderedSetOf((byte)0xA0, implCerts); 511 } 512 513 // CRLs (optional) 514 if (crls != null && crls.length != 0) { 515 // cast to X509CRLImpl[] since X509CRLImpl implements DerEncoder 516 Set<X509CRLImpl> implCRLs = new HashSet<X509CRLImpl>(crls.length); 517 for (X509CRL crl: crls) { 518 if (crl instanceof X509CRLImpl) 519 implCRLs.add((X509CRLImpl) crl); 520 else { 521 try { 522 byte[] encoded = crl.getEncoded(); 523 implCRLs.add(new X509CRLImpl(encoded)); 524 } catch (CRLException ce) { 525 IOException ie = new IOException(ce.getMessage()); 526 ie.initCause(ce); 527 throw ie; 528 } 529 } 530 } 531 532 // Add the CRL set (tagged with [1] IMPLICIT) 533 // to the signed data 534 signedData.putOrderedSetOf((byte)0xA1, 535 implCRLs.toArray(new X509CRLImpl[implCRLs.size()])); 536 } 537 538 // signerInfos 539 signedData.putOrderedSetOf(DerValue.tag_Set, signerInfos); 540 541 // making it a signed data block 542 DerValue signedDataSeq = new DerValue(DerValue.tag_Sequence, 543 signedData.toByteArray()); 544 545 // making it a content info sequence 546 ContentInfo block = new ContentInfo(ContentInfo.SIGNED_DATA_OID, 547 signedDataSeq); 548 549 // writing out the contentInfo sequence 550 block.encode(out); 551 } 552 553 /** 554 * This verifies a given SignerInfo. 555 * 556 * @param info the signer information. 557 * @param bytes the DER encoded content information. 558 * 559 * @exception NoSuchAlgorithmException on unrecognized algorithms. 560 * @exception SignatureException on signature handling errors. 561 */ 562 public SignerInfo verify(SignerInfo info, byte[] bytes) 563 throws NoSuchAlgorithmException, SignatureException { 564 return info.verify(this, bytes); 565 } 566 567 /** 568 * This verifies a given SignerInfo. 569 * 570 * @param info the signer information. 571 * @param dataInputStream the DER encoded content information. 572 * 573 * @exception NoSuchAlgorithmException on unrecognized algorithms. 574 * @exception SignatureException on signature handling errors. 575 */ 576 public SignerInfo verify(SignerInfo info, InputStream dataInputStream) 577 throws NoSuchAlgorithmException, SignatureException, IOException { 578 return info.verify(this, dataInputStream); 579 } 580 581 /** 582 * Returns all signerInfos which self-verify. 583 * 584 * @param bytes the DER encoded content information. 585 * 586 * @exception NoSuchAlgorithmException on unrecognized algorithms. 587 * @exception SignatureException on signature handling errors. 588 */ 589 public SignerInfo[] verify(byte[] bytes) 590 throws NoSuchAlgorithmException, SignatureException { 591 592 Vector<SignerInfo> intResult = new Vector<SignerInfo>(); 593 for (int i = 0; i < signerInfos.length; i++) { 594 595 SignerInfo signerInfo = verify(signerInfos[i], bytes); 596 if (signerInfo != null) { 597 intResult.addElement(signerInfo); 598 } 599 } 600 if (intResult.size() != 0) { 601 602 SignerInfo[] result = new SignerInfo[intResult.size()]; 603 intResult.copyInto(result); 604 return result; 605 } 606 return null; 607 } 608 609 /** 610 * Returns all signerInfos which self-verify. 611 * 612 * @exception NoSuchAlgorithmException on unrecognized algorithms. 613 * @exception SignatureException on signature handling errors. 614 */ 615 public SignerInfo[] verify() 616 throws NoSuchAlgorithmException, SignatureException { 617 return verify(null); 618 } 619 620 /** 621 * Returns the version number of this PKCS7 block. 622 * @return the version or null if version is not specified 623 * for the content type. 624 */ 625 public BigInteger getVersion() { 626 return version; 627 } 628 629 /** 630 * Returns the message digest algorithms specified in this PKCS7 block. 631 * @return the array of Digest Algorithms or null if none are specified 632 * for the content type. 633 */ 634 public AlgorithmId[] getDigestAlgorithmIds() { 635 return digestAlgorithmIds; 636 } 637 638 /** 639 * Returns the content information specified in this PKCS7 block. 640 */ 641 public ContentInfo getContentInfo() { 642 return contentInfo; 643 } 644 645 /** 646 * Returns the X.509 certificates listed in this PKCS7 block. 647 * @return a clone of the array of X.509 certificates or null if 648 * none are specified for the content type. 649 */ 650 public X509Certificate[] getCertificates() { 651 if (certificates != null) 652 return certificates.clone(); 653 else 654 return null; 655 } 656 657 /** 658 * Returns the X.509 crls listed in this PKCS7 block. 659 * @return a clone of the array of X.509 crls or null if none 660 * are specified for the content type. 661 */ 662 public X509CRL[] getCRLs() { 663 if (crls != null) 664 return crls.clone(); 665 else 666 return null; 667 } 668 669 /** 670 * Returns the signer's information specified in this PKCS7 block. 671 * @return the array of Signer Infos or null if none are specified 672 * for the content type. 673 */ 674 public SignerInfo[] getSignerInfos() { 675 return signerInfos; 676 } 677 678 /** 679 * Returns the X.509 certificate listed in this PKCS7 block 680 * which has a matching serial number and Issuer name, or 681 * null if one is not found. 682 * 683 * @param serial the serial number of the certificate to retrieve. 684 * @param issuerName the Distinguished Name of the Issuer. 685 */ 686 public X509Certificate getCertificate(BigInteger serial, X500Name issuerName) { 687 if (certificates != null) { 688 if (certIssuerNames == null) 689 populateCertIssuerNames(); 690 for (int i = 0; i < certificates.length; i++) { 691 X509Certificate cert = certificates[i]; 692 BigInteger thisSerial = cert.getSerialNumber(); 693 if (serial.equals(thisSerial) 694 && issuerName.equals(certIssuerNames[i])) 695 { 696 return cert; 697 } 698 } 699 } 700 return null; 701 } 702 703 /** 704 * Populate array of Issuer DNs from certificates and convert 705 * each Principal to type X500Name if necessary. 706 */ 707 private void populateCertIssuerNames() { 708 if (certificates == null) 709 return; 710 711 certIssuerNames = new Principal[certificates.length]; 712 for (int i = 0; i < certificates.length; i++) { 713 X509Certificate cert = certificates[i]; 714 Principal certIssuerName = cert.getIssuerDN(); 715 if (!(certIssuerName instanceof X500Name)) { 716 // must extract the original encoded form of DN for 717 // subsequent name comparison checks (converting to a 718 // String and back to an encoded DN could cause the 719 // types of String attribute values to be changed) 720 try { 721 X509CertInfo tbsCert = 722 new X509CertInfo(cert.getTBSCertificate()); 723 certIssuerName = (Principal) 724 tbsCert.get(CertificateIssuerName.NAME + "." + 725 CertificateIssuerName.DN_NAME); 726 } catch (Exception e) { 727 // error generating X500Name object from the cert's 728 // issuer DN, leave name as is. 729 } 730 } 731 certIssuerNames[i] = certIssuerName; 732 } 733 } 734 735 /** 736 * Returns the PKCS7 block in a printable string form. 737 */ 738 public String toString() { 739 String out = ""; 740 741 out += contentInfo + "\n"; 742 if (version != null) 743 out += "PKCS7 :: version: " + Debug.toHexString(version) + "\n"; 744 if (digestAlgorithmIds != null) { 745 out += "PKCS7 :: digest AlgorithmIds: \n"; 746 for (int i = 0; i < digestAlgorithmIds.length; i++) 747 out += "\t" + digestAlgorithmIds[i] + "\n"; 748 } 749 if (certificates != null) { 750 out += "PKCS7 :: certificates: \n"; 751 for (int i = 0; i < certificates.length; i++) 752 out += "\t" + i + ". " + certificates[i] + "\n"; 753 } 754 if (crls != null) { 755 out += "PKCS7 :: crls: \n"; 756 for (int i = 0; i < crls.length; i++) 757 out += "\t" + i + ". " + crls[i] + "\n"; 758 } 759 if (signerInfos != null) { 760 out += "PKCS7 :: signer infos: \n"; 761 for (int i = 0; i < signerInfos.length; i++) 762 out += ("\t" + i + ". " + signerInfos[i] + "\n"); 763 } 764 return out; 765 } 766 767 /** 768 * Returns true if this is a JDK1.1.x-style PKCS#7 block, and false 769 * otherwise. 770 */ 771 public boolean isOldStyle() { 772 return this.oldStyle; 773 } 774 775 /** 776 * For legacy reasons we need to return exactly the original encoded certificate bytes, instead 777 * of letting the underlying implementation have a shot at re-encoding the data. 778 */ 779 private static class VerbatimX509Certificate extends WrappedX509Certificate { 780 private byte[] encodedVerbatim; 781 782 public VerbatimX509Certificate(X509Certificate wrapped, byte[] encodedVerbatim) { 783 super(wrapped); 784 this.encodedVerbatim = encodedVerbatim; 785 } 786 787 @Override 788 public byte[] getEncoded() throws CertificateEncodingException { 789 return encodedVerbatim; 790 } 791 } 792 793 private static class WrappedX509Certificate extends X509Certificate { 794 private final X509Certificate wrapped; 795 796 public WrappedX509Certificate(X509Certificate wrapped) { 797 this.wrapped = wrapped; 798 } 799 800 @Override 801 public Set<String> getCriticalExtensionOIDs() { 802 return wrapped.getCriticalExtensionOIDs(); 803 } 804 805 @Override 806 public byte[] getExtensionValue(String oid) { 807 return wrapped.getExtensionValue(oid); 808 } 809 810 @Override 811 public Set<String> getNonCriticalExtensionOIDs() { 812 return wrapped.getNonCriticalExtensionOIDs(); 813 } 814 815 @Override 816 public boolean hasUnsupportedCriticalExtension() { 817 return wrapped.hasUnsupportedCriticalExtension(); 818 } 819 820 @Override 821 public void checkValidity() 822 throws CertificateExpiredException, CertificateNotYetValidException { 823 wrapped.checkValidity(); 824 } 825 826 @Override 827 public void checkValidity(Date date) 828 throws CertificateExpiredException, CertificateNotYetValidException { 829 wrapped.checkValidity(date); 830 } 831 832 @Override 833 public int getVersion() { 834 return wrapped.getVersion(); 835 } 836 837 @Override 838 public BigInteger getSerialNumber() { 839 return wrapped.getSerialNumber(); 840 } 841 842 @Override 843 public Principal getIssuerDN() { 844 return wrapped.getIssuerDN(); 845 } 846 847 @Override 848 public Principal getSubjectDN() { 849 return wrapped.getSubjectDN(); 850 } 851 852 @Override 853 public Date getNotBefore() { 854 return wrapped.getNotBefore(); 855 } 856 857 @Override 858 public Date getNotAfter() { 859 return wrapped.getNotAfter(); 860 } 861 862 @Override 863 public byte[] getTBSCertificate() throws CertificateEncodingException { 864 return wrapped.getTBSCertificate(); 865 } 866 867 @Override 868 public byte[] getSignature() { 869 return wrapped.getSignature(); 870 } 871 872 @Override 873 public String getSigAlgName() { 874 return wrapped.getSigAlgName(); 875 } 876 877 @Override 878 public String getSigAlgOID() { 879 return wrapped.getSigAlgOID(); 880 } 881 882 @Override 883 public byte[] getSigAlgParams() { 884 return wrapped.getSigAlgParams(); 885 } 886 887 @Override 888 public boolean[] getIssuerUniqueID() { 889 return wrapped.getIssuerUniqueID(); 890 } 891 892 @Override 893 public boolean[] getSubjectUniqueID() { 894 return wrapped.getSubjectUniqueID(); 895 } 896 897 @Override 898 public boolean[] getKeyUsage() { 899 return wrapped.getKeyUsage(); 900 } 901 902 @Override 903 public int getBasicConstraints() { 904 return wrapped.getBasicConstraints(); 905 } 906 907 @Override 908 public byte[] getEncoded() throws CertificateEncodingException { 909 return wrapped.getEncoded(); 910 } 911 912 @Override 913 public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException, 914 InvalidKeyException, NoSuchProviderException, SignatureException { 915 wrapped.verify(key); 916 } 917 918 @Override 919 public void verify(PublicKey key, String sigProvider) 920 throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, 921 NoSuchProviderException, SignatureException { 922 wrapped.verify(key, sigProvider); 923 } 924 925 @Override 926 public String toString() { 927 return wrapped.toString(); 928 } 929 930 @Override 931 public PublicKey getPublicKey() { 932 return wrapped.getPublicKey(); 933 } 934 935 @Override 936 public List<String> getExtendedKeyUsage() throws CertificateParsingException { 937 return wrapped.getExtendedKeyUsage(); 938 } 939 940 @Override 941 public Collection<List<?>> getIssuerAlternativeNames() throws CertificateParsingException { 942 return wrapped.getIssuerAlternativeNames(); 943 } 944 945 @Override 946 public X500Principal getIssuerX500Principal() { 947 return wrapped.getIssuerX500Principal(); 948 } 949 950 @Override 951 public Collection<List<?>> getSubjectAlternativeNames() throws CertificateParsingException { 952 return wrapped.getSubjectAlternativeNames(); 953 } 954 955 @Override 956 public X500Principal getSubjectX500Principal() { 957 return wrapped.getSubjectX500Principal(); 958 } 959 960 @Override 961 public void verify(PublicKey key, Provider sigProvider) throws CertificateException, 962 NoSuchAlgorithmException, InvalidKeyException, SignatureException { 963 wrapped.verify(key, sigProvider); 964 } 965 } 966 } 967