1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 1996, 2013, 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.net.URI; 32 import java.util.*; 33 import java.security.cert.X509Certificate; 34 import java.security.cert.CertificateException; 35 import java.security.cert.CertificateEncodingException; 36 import java.security.cert.CertificateExpiredException; 37 import java.security.cert.CertificateNotYetValidException; 38 import java.security.cert.CertificateParsingException; 39 import java.security.cert.X509CRL; 40 import java.security.cert.CRLException; 41 import java.security.cert.CertificateFactory; 42 import java.security.*; 43 44 import sun.security.timestamp.*; 45 46 import javax.security.auth.x500.X500Principal; 47 48 import sun.security.util.*; 49 import sun.security.x509.AlgorithmId; 50 import sun.security.x509.X509CertImpl; 51 import sun.security.x509.X509CertInfo; 52 import sun.security.x509.X509CRLImpl; 53 import sun.security.x509.X500Name; 54 55 /** 56 * PKCS7 as defined in RSA Laboratories PKCS7 Technical Note. Profile 57 * Supports only <tt>SignedData</tt> ContentInfo 58 * type, where to the type of data signed is plain Data. 59 * For signedData, <tt>crls</tt>, <tt>attributes</tt> and 60 * PKCS#6 Extended Certificates are not supported. 61 * 62 * @author Benjamin Renaud 63 */ 64 public class PKCS7 { 65 66 private ObjectIdentifier contentType; 67 68 // the ASN.1 members for a signedData (and other) contentTypes 69 private BigInteger version = null; 70 private AlgorithmId[] digestAlgorithmIds = null; 71 private ContentInfo contentInfo = null; 72 private X509Certificate[] certificates = null; 73 private X509CRL[] crls = null; 74 private SignerInfo[] signerInfos = null; 75 76 private boolean oldStyle = false; // Is this JDK1.1.x-style? 77 78 private Principal[] certIssuerNames; 79 80 // BEGIN Android-removed: unused in Android 81 /* 82 /* 83 * Random number generator for creating nonce values 84 * (Lazy initialization) 85 * 86 private static class SecureRandomHolder { 87 static final SecureRandom RANDOM; 88 static { 89 SecureRandom tmp = null; 90 try { 91 tmp = SecureRandom.getInstance("SHA1PRNG"); 92 } catch (NoSuchAlgorithmException e) { 93 // should not happen 94 } 95 RANDOM = tmp; 96 } 97 } 98 99 /* 100 * Object identifier for the timestamping key purpose. 101 * 102 private static final String KP_TIMESTAMPING_OID = "1.3.6.1.5.5.7.3.8"; 103 104 /* 105 * Object identifier for extendedKeyUsage extension 106 * 107 private static final String EXTENDED_KEY_USAGE_OID = "2.5.29.37"; 108 */ 109 // END Android-removed: unused on Android 110 111 /** 112 * Unmarshals a PKCS7 block from its encoded form, parsing the 113 * encoded bytes from the InputStream. 114 * 115 * @param in an input stream holding at least one PKCS7 block. 116 * @exception ParsingException on parsing errors. 117 * @exception IOException on other errors. 118 */ PKCS7(InputStream in)119 public PKCS7(InputStream in) throws ParsingException, IOException { 120 DataInputStream dis = new DataInputStream(in); 121 byte[] data = new byte[dis.available()]; 122 dis.readFully(data); 123 124 parse(new DerInputStream(data)); 125 } 126 127 /** 128 * Unmarshals a PKCS7 block from its encoded form, parsing the 129 * encoded bytes from the DerInputStream. 130 * 131 * @param derin a DerInputStream holding at least one PKCS7 block. 132 * @exception ParsingException on parsing errors. 133 */ PKCS7(DerInputStream derin)134 public PKCS7(DerInputStream derin) throws ParsingException { 135 parse(derin); 136 } 137 138 /** 139 * Unmarshals a PKCS7 block from its encoded form, parsing the 140 * encoded bytes. 141 * 142 * @param bytes the encoded bytes. 143 * @exception ParsingException on parsing errors. 144 */ PKCS7(byte[] bytes)145 public PKCS7(byte[] bytes) throws ParsingException { 146 try { 147 DerInputStream derin = new DerInputStream(bytes); 148 parse(derin); 149 } catch (IOException ioe1) { 150 ParsingException pe = new ParsingException( 151 "Unable to parse the encoded bytes"); 152 pe.initCause(ioe1); 153 throw pe; 154 } 155 } 156 157 /* 158 * Parses a PKCS#7 block. 159 */ parse(DerInputStream derin)160 private void parse(DerInputStream derin) 161 throws ParsingException 162 { 163 try { 164 derin.mark(derin.available()); 165 // try new (i.e., JDK1.2) style 166 parse(derin, false); 167 } catch (IOException ioe) { 168 try { 169 derin.reset(); 170 // try old (i.e., JDK1.1.x) style 171 parse(derin, true); 172 oldStyle = true; 173 } catch (IOException ioe1) { 174 ParsingException pe = new ParsingException( 175 ioe1.getMessage()); 176 pe.initCause(ioe); 177 pe.addSuppressed(ioe1); 178 throw pe; 179 } 180 } 181 } 182 183 /** 184 * Parses a PKCS#7 block. 185 * 186 * @param derin the ASN.1 encoding of the PKCS#7 block. 187 * @param oldStyle flag indicating whether or not the given PKCS#7 block 188 * is encoded according to JDK1.1.x. 189 */ parse(DerInputStream derin, boolean oldStyle)190 private void parse(DerInputStream derin, boolean oldStyle) 191 throws IOException 192 { 193 contentInfo = new ContentInfo(derin, oldStyle); 194 contentType = contentInfo.contentType; 195 DerValue content = contentInfo.getContent(); 196 197 if (contentType.equals((Object)ContentInfo.SIGNED_DATA_OID)) { 198 parseSignedData(content); 199 } else if (contentType.equals((Object)ContentInfo.OLD_SIGNED_DATA_OID)) { 200 // This is for backwards compatibility with JDK 1.1.x 201 parseOldSignedData(content); 202 } else if (contentType.equals((Object) 203 ContentInfo.NETSCAPE_CERT_SEQUENCE_OID)){ 204 parseNetscapeCertChain(content); 205 } else { 206 throw new ParsingException("content type " + contentType + 207 " not supported."); 208 } 209 } 210 211 /** 212 * Construct an initialized PKCS7 block. 213 * 214 * @param digestAlgorithmIds the message digest algorithm identifiers. 215 * @param contentInfo the content information. 216 * @param certificates an array of X.509 certificates. 217 * @param crls an array of CRLs 218 * @param signerInfos an array of signer information. 219 */ PKCS7(AlgorithmId[] digestAlgorithmIds, ContentInfo contentInfo, X509Certificate[] certificates, X509CRL[] crls, SignerInfo[] signerInfos)220 public PKCS7(AlgorithmId[] digestAlgorithmIds, 221 ContentInfo contentInfo, 222 X509Certificate[] certificates, 223 X509CRL[] crls, 224 SignerInfo[] signerInfos) { 225 226 version = BigInteger.ONE; 227 this.digestAlgorithmIds = digestAlgorithmIds; 228 this.contentInfo = contentInfo; 229 this.certificates = certificates; 230 this.crls = crls; 231 this.signerInfos = signerInfos; 232 } 233 PKCS7(AlgorithmId[] digestAlgorithmIds, ContentInfo contentInfo, X509Certificate[] certificates, SignerInfo[] signerInfos)234 public PKCS7(AlgorithmId[] digestAlgorithmIds, 235 ContentInfo contentInfo, 236 X509Certificate[] certificates, 237 SignerInfo[] signerInfos) { 238 this(digestAlgorithmIds, contentInfo, certificates, null, signerInfos); 239 } 240 parseNetscapeCertChain(DerValue val)241 private void parseNetscapeCertChain(DerValue val) 242 throws ParsingException, IOException { 243 DerInputStream dis = new DerInputStream(val.toByteArray()); 244 DerValue[] contents = dis.getSequence(2, true); 245 certificates = new X509Certificate[contents.length]; 246 247 CertificateFactory certfac = null; 248 try { 249 certfac = CertificateFactory.getInstance("X.509"); 250 } catch (CertificateException ce) { 251 // do nothing 252 } 253 254 for (int i=0; i < contents.length; i++) { 255 ByteArrayInputStream bais = null; 256 try { 257 byte[] original = contents[i].getOriginalEncodedForm(); 258 if (certfac == null) 259 certificates[i] = new X509CertImpl(contents[i], original); 260 else { 261 bais = new ByteArrayInputStream(original); 262 certificates[i] = new VerbatimX509Certificate( 263 (X509Certificate)certfac.generateCertificate(bais), 264 original); 265 bais.close(); 266 bais = null; 267 } 268 } catch (CertificateException ce) { 269 ParsingException pe = new ParsingException(ce.getMessage()); 270 pe.initCause(ce); 271 throw pe; 272 } catch (IOException ioe) { 273 ParsingException pe = new ParsingException(ioe.getMessage()); 274 pe.initCause(ioe); 275 throw pe; 276 } finally { 277 if (bais != null) 278 bais.close(); 279 } 280 } 281 } 282 parseSignedData(DerValue val)283 private void parseSignedData(DerValue val) 284 throws ParsingException, IOException { 285 286 DerInputStream dis = val.toDerInputStream(); 287 288 // Version 289 version = dis.getBigInteger(); 290 291 // digestAlgorithmIds 292 DerValue[] digestAlgorithmIdVals = dis.getSet(1); 293 int len = digestAlgorithmIdVals.length; 294 digestAlgorithmIds = new AlgorithmId[len]; 295 try { 296 for (int i = 0; i < len; i++) { 297 DerValue oid = digestAlgorithmIdVals[i]; 298 digestAlgorithmIds[i] = AlgorithmId.parse(oid); 299 } 300 301 } catch (IOException e) { 302 ParsingException pe = 303 new ParsingException("Error parsing digest AlgorithmId IDs: " + 304 e.getMessage()); 305 pe.initCause(e); 306 throw pe; 307 } 308 // contentInfo 309 contentInfo = new ContentInfo(dis); 310 311 CertificateFactory certfac = null; 312 try { 313 certfac = CertificateFactory.getInstance("X.509"); 314 } catch (CertificateException ce) { 315 // do nothing 316 } 317 318 /* 319 * check if certificates (implicit tag) are provided 320 * (certificates are OPTIONAL) 321 */ 322 if ((byte)(dis.peekByte()) == (byte)0xA0) { 323 DerValue[] certVals = dis.getSet(2, true, true); 324 325 len = certVals.length; 326 certificates = new X509Certificate[len]; 327 int count = 0; 328 329 for (int i = 0; i < len; i++) { 330 ByteArrayInputStream bais = null; 331 try { 332 byte tag = certVals[i].getTag(); 333 // We only parse the normal certificate. Other types of 334 // CertificateChoices ignored. 335 if (tag == DerValue.tag_Sequence) { 336 byte[] original = certVals[i].getOriginalEncodedForm(); 337 if (certfac == null) { 338 certificates[count] = new X509CertImpl(certVals[i], original); 339 } else { 340 bais = new ByteArrayInputStream(original); 341 certificates[count] = new VerbatimX509Certificate( 342 (X509Certificate)certfac.generateCertificate(bais), 343 original); 344 bais.close(); 345 bais = null; 346 } 347 count++; 348 } 349 } catch (CertificateException ce) { 350 ParsingException pe = new ParsingException(ce.getMessage()); 351 pe.initCause(ce); 352 throw pe; 353 } catch (IOException ioe) { 354 ParsingException pe = new ParsingException(ioe.getMessage()); 355 pe.initCause(ioe); 356 throw pe; 357 } finally { 358 if (bais != null) 359 bais.close(); 360 } 361 } 362 if (count != len) { 363 certificates = Arrays.copyOf(certificates, count); 364 } 365 } 366 367 // check if crls (implicit tag) are provided (crls are OPTIONAL) 368 if ((byte)(dis.peekByte()) == (byte)0xA1) { 369 DerValue[] crlVals = dis.getSet(1, true); 370 371 len = crlVals.length; 372 crls = new X509CRL[len]; 373 374 for (int i = 0; i < len; i++) { 375 ByteArrayInputStream bais = null; 376 try { 377 if (certfac == null) 378 crls[i] = new X509CRLImpl(crlVals[i]); 379 else { 380 byte[] encoded = crlVals[i].toByteArray(); 381 bais = new ByteArrayInputStream(encoded); 382 crls[i] = (X509CRL) certfac.generateCRL(bais); 383 bais.close(); 384 bais = null; 385 } 386 } catch (CRLException e) { 387 ParsingException pe = 388 new ParsingException(e.getMessage()); 389 pe.initCause(e); 390 throw pe; 391 } finally { 392 if (bais != null) 393 bais.close(); 394 } 395 } 396 } 397 398 // signerInfos 399 DerValue[] signerInfoVals = dis.getSet(1); 400 401 len = signerInfoVals.length; 402 signerInfos = new SignerInfo[len]; 403 404 for (int i = 0; i < len; i++) { 405 DerInputStream in = signerInfoVals[i].toDerInputStream(); 406 signerInfos[i] = new SignerInfo(in); 407 } 408 } 409 410 /* 411 * Parses an old-style SignedData encoding (for backwards 412 * compatibility with JDK1.1.x). 413 */ parseOldSignedData(DerValue val)414 private void parseOldSignedData(DerValue val) 415 throws ParsingException, IOException 416 { 417 DerInputStream dis = val.toDerInputStream(); 418 419 // Version 420 version = dis.getBigInteger(); 421 422 // digestAlgorithmIds 423 DerValue[] digestAlgorithmIdVals = dis.getSet(1); 424 int len = digestAlgorithmIdVals.length; 425 426 digestAlgorithmIds = new AlgorithmId[len]; 427 try { 428 for (int i = 0; i < len; i++) { 429 DerValue oid = digestAlgorithmIdVals[i]; 430 digestAlgorithmIds[i] = AlgorithmId.parse(oid); 431 } 432 } catch (IOException e) { 433 throw new ParsingException("Error parsing digest AlgorithmId IDs"); 434 } 435 436 // contentInfo 437 contentInfo = new ContentInfo(dis, true); 438 439 // certificates 440 CertificateFactory certfac = null; 441 try { 442 certfac = CertificateFactory.getInstance("X.509"); 443 } catch (CertificateException ce) { 444 // do nothing 445 } 446 DerValue[] certVals = dis.getSet(2, false, true); 447 len = certVals.length; 448 certificates = new X509Certificate[len]; 449 450 for (int i = 0; i < len; i++) { 451 ByteArrayInputStream bais = null; 452 try { 453 byte[] original = certVals[i].getOriginalEncodedForm(); 454 if (certfac == null) 455 certificates[i] = new X509CertImpl(certVals[i], original); 456 else { 457 bais = new ByteArrayInputStream(original); 458 certificates[i] = new VerbatimX509Certificate( 459 (X509Certificate)certfac.generateCertificate(bais), 460 original); 461 bais.close(); 462 bais = null; 463 } 464 } catch (CertificateException ce) { 465 ParsingException pe = new ParsingException(ce.getMessage()); 466 pe.initCause(ce); 467 throw pe; 468 } catch (IOException ioe) { 469 ParsingException pe = new ParsingException(ioe.getMessage()); 470 pe.initCause(ioe); 471 throw pe; 472 } finally { 473 if (bais != null) 474 bais.close(); 475 } 476 } 477 478 // crls are ignored. 479 dis.getSet(0); 480 481 // signerInfos 482 DerValue[] signerInfoVals = dis.getSet(1); 483 len = signerInfoVals.length; 484 signerInfos = new SignerInfo[len]; 485 for (int i = 0; i < len; i++) { 486 DerInputStream in = signerInfoVals[i].toDerInputStream(); 487 signerInfos[i] = new SignerInfo(in, true); 488 } 489 } 490 491 /** 492 * Encodes the signed data to an output stream. 493 * 494 * @param out the output stream to write the encoded data to. 495 * @exception IOException on encoding errors. 496 */ encodeSignedData(OutputStream out)497 public void encodeSignedData(OutputStream out) throws IOException { 498 DerOutputStream derout = new DerOutputStream(); 499 encodeSignedData(derout); 500 out.write(derout.toByteArray()); 501 } 502 503 /** 504 * Encodes the signed data to a DerOutputStream. 505 * 506 * @param out the DerOutputStream to write the encoded data to. 507 * @exception IOException on encoding errors. 508 */ encodeSignedData(DerOutputStream out)509 public void encodeSignedData(DerOutputStream out) 510 throws IOException 511 { 512 DerOutputStream signedData = new DerOutputStream(); 513 514 // version 515 signedData.putInteger(version); 516 517 // digestAlgorithmIds 518 signedData.putOrderedSetOf(DerValue.tag_Set, digestAlgorithmIds); 519 520 // contentInfo 521 contentInfo.encode(signedData); 522 523 // certificates (optional) 524 if (certificates != null && certificates.length != 0) { 525 // cast to X509CertImpl[] since X509CertImpl implements DerEncoder 526 X509CertImpl implCerts[] = new X509CertImpl[certificates.length]; 527 for (int i = 0; i < certificates.length; i++) { 528 if (certificates[i] instanceof X509CertImpl) 529 implCerts[i] = (X509CertImpl) certificates[i]; 530 else { 531 try { 532 byte[] encoded = certificates[i].getEncoded(); 533 implCerts[i] = new X509CertImpl(encoded); 534 } catch (CertificateException ce) { 535 throw new IOException(ce); 536 } 537 } 538 } 539 540 // Add the certificate set (tagged with [0] IMPLICIT) 541 // to the signed data 542 signedData.putOrderedSetOf((byte)0xA0, implCerts); 543 } 544 545 // CRLs (optional) 546 if (crls != null && crls.length != 0) { 547 // cast to X509CRLImpl[] since X509CRLImpl implements DerEncoder 548 Set<X509CRLImpl> implCRLs = new HashSet<X509CRLImpl>(crls.length); 549 for (X509CRL crl: crls) { 550 if (crl instanceof X509CRLImpl) 551 implCRLs.add((X509CRLImpl) crl); 552 else { 553 try { 554 byte[] encoded = crl.getEncoded(); 555 implCRLs.add(new X509CRLImpl(encoded)); 556 } catch (CRLException ce) { 557 throw new IOException(ce); 558 } 559 } 560 } 561 562 // Add the CRL set (tagged with [1] IMPLICIT) 563 // to the signed data 564 signedData.putOrderedSetOf((byte)0xA1, 565 implCRLs.toArray(new X509CRLImpl[implCRLs.size()])); 566 } 567 568 // signerInfos 569 signedData.putOrderedSetOf(DerValue.tag_Set, signerInfos); 570 571 // making it a signed data block 572 DerValue signedDataSeq = new DerValue(DerValue.tag_Sequence, 573 signedData.toByteArray()); 574 575 // making it a content info sequence 576 ContentInfo block = new ContentInfo(ContentInfo.SIGNED_DATA_OID, 577 signedDataSeq); 578 579 // writing out the contentInfo sequence 580 block.encode(out); 581 } 582 583 /** 584 * This verifies a given SignerInfo. 585 * 586 * @param info the signer information. 587 * @param bytes the DER encoded content information. 588 * 589 * @exception NoSuchAlgorithmException on unrecognized algorithms. 590 * @exception SignatureException on signature handling errors. 591 */ verify(SignerInfo info, byte[] bytes)592 public SignerInfo verify(SignerInfo info, byte[] bytes) 593 throws NoSuchAlgorithmException, SignatureException { 594 return info.verify(this, bytes); 595 } 596 597 /** 598 * This verifies a given SignerInfo. 599 * 600 * @param info the signer information. 601 * @param dataInputStream the DER encoded content information. 602 * 603 * @exception NoSuchAlgorithmException on unrecognized algorithms. 604 * @exception SignatureException on signature handling errors. 605 */ verify(SignerInfo info, InputStream dataInputStream)606 public SignerInfo verify(SignerInfo info, InputStream dataInputStream) 607 throws NoSuchAlgorithmException, SignatureException, IOException { 608 return info.verify(this, dataInputStream); 609 } 610 611 /** 612 * Returns all signerInfos which self-verify. 613 * 614 * @param bytes the DER encoded content information. 615 * 616 * @exception NoSuchAlgorithmException on unrecognized algorithms. 617 * @exception SignatureException on signature handling errors. 618 */ verify(byte[] bytes)619 public SignerInfo[] verify(byte[] bytes) 620 throws NoSuchAlgorithmException, SignatureException { 621 622 Vector<SignerInfo> intResult = new Vector<SignerInfo>(); 623 for (int i = 0; i < signerInfos.length; i++) { 624 625 SignerInfo signerInfo = verify(signerInfos[i], bytes); 626 if (signerInfo != null) { 627 intResult.addElement(signerInfo); 628 } 629 } 630 if (!intResult.isEmpty()) { 631 632 SignerInfo[] result = new SignerInfo[intResult.size()]; 633 intResult.copyInto(result); 634 return result; 635 } 636 return null; 637 } 638 639 /** 640 * Returns all signerInfos which self-verify. 641 * 642 * @exception NoSuchAlgorithmException on unrecognized algorithms. 643 * @exception SignatureException on signature handling errors. 644 */ verify()645 public SignerInfo[] verify() 646 throws NoSuchAlgorithmException, SignatureException { 647 return verify(null); 648 } 649 650 /** 651 * Returns the version number of this PKCS7 block. 652 * @return the version or null if version is not specified 653 * for the content type. 654 */ getVersion()655 public BigInteger getVersion() { 656 return version; 657 } 658 659 /** 660 * Returns the message digest algorithms specified in this PKCS7 block. 661 * @return the array of Digest Algorithms or null if none are specified 662 * for the content type. 663 */ getDigestAlgorithmIds()664 public AlgorithmId[] getDigestAlgorithmIds() { 665 return digestAlgorithmIds; 666 } 667 668 /** 669 * Returns the content information specified in this PKCS7 block. 670 */ getContentInfo()671 public ContentInfo getContentInfo() { 672 return contentInfo; 673 } 674 675 /** 676 * Returns the X.509 certificates listed in this PKCS7 block. 677 * @return a clone of the array of X.509 certificates or null if 678 * none are specified for the content type. 679 */ getCertificates()680 public X509Certificate[] getCertificates() { 681 if (certificates != null) 682 return certificates.clone(); 683 else 684 return null; 685 } 686 687 /** 688 * Returns the X.509 crls listed in this PKCS7 block. 689 * @return a clone of the array of X.509 crls or null if none 690 * are specified for the content type. 691 */ getCRLs()692 public X509CRL[] getCRLs() { 693 if (crls != null) 694 return crls.clone(); 695 else 696 return null; 697 } 698 699 /** 700 * Returns the signer's information specified in this PKCS7 block. 701 * @return the array of Signer Infos or null if none are specified 702 * for the content type. 703 */ getSignerInfos()704 public SignerInfo[] getSignerInfos() { 705 return signerInfos; 706 } 707 708 /** 709 * Returns the X.509 certificate listed in this PKCS7 block 710 * which has a matching serial number and Issuer name, or 711 * null if one is not found. 712 * 713 * @param serial the serial number of the certificate to retrieve. 714 * @param issuerName the Distinguished Name of the Issuer. 715 */ getCertificate(BigInteger serial, X500Name issuerName)716 public X509Certificate getCertificate(BigInteger serial, X500Name issuerName) { 717 if (certificates != null) { 718 if (certIssuerNames == null) 719 populateCertIssuerNames(); 720 for (int i = 0; i < certificates.length; i++) { 721 X509Certificate cert = certificates[i]; 722 BigInteger thisSerial = cert.getSerialNumber(); 723 if (serial.equals(thisSerial) 724 && issuerName.equals(certIssuerNames[i])) 725 { 726 return cert; 727 } 728 } 729 } 730 return null; 731 } 732 733 /** 734 * Populate array of Issuer DNs from certificates and convert 735 * each Principal to type X500Name if necessary. 736 */ populateCertIssuerNames()737 private void populateCertIssuerNames() { 738 if (certificates == null) 739 return; 740 741 certIssuerNames = new Principal[certificates.length]; 742 for (int i = 0; i < certificates.length; i++) { 743 X509Certificate cert = certificates[i]; 744 Principal certIssuerName = cert.getIssuerDN(); 745 if (!(certIssuerName instanceof X500Name)) { 746 // must extract the original encoded form of DN for 747 // subsequent name comparison checks (converting to a 748 // String and back to an encoded DN could cause the 749 // types of String attribute values to be changed) 750 try { 751 X509CertInfo tbsCert = 752 new X509CertInfo(cert.getTBSCertificate()); 753 certIssuerName = (Principal) 754 tbsCert.get(X509CertInfo.ISSUER + "." + 755 X509CertInfo.DN_NAME); 756 } catch (Exception e) { 757 // error generating X500Name object from the cert's 758 // issuer DN, leave name as is. 759 } 760 } 761 certIssuerNames[i] = certIssuerName; 762 } 763 } 764 765 /** 766 * Returns the PKCS7 block in a printable string form. 767 */ toString()768 public String toString() { 769 String out = ""; 770 771 out += contentInfo + "\n"; 772 if (version != null) 773 out += "PKCS7 :: version: " + Debug.toHexString(version) + "\n"; 774 if (digestAlgorithmIds != null) { 775 out += "PKCS7 :: digest AlgorithmIds: \n"; 776 for (int i = 0; i < digestAlgorithmIds.length; i++) 777 out += "\t" + digestAlgorithmIds[i] + "\n"; 778 } 779 if (certificates != null) { 780 out += "PKCS7 :: certificates: \n"; 781 for (int i = 0; i < certificates.length; i++) 782 out += "\t" + i + ". " + certificates[i] + "\n"; 783 } 784 if (crls != null) { 785 out += "PKCS7 :: crls: \n"; 786 for (int i = 0; i < crls.length; i++) 787 out += "\t" + i + ". " + crls[i] + "\n"; 788 } 789 if (signerInfos != null) { 790 out += "PKCS7 :: signer infos: \n"; 791 for (int i = 0; i < signerInfos.length; i++) 792 out += ("\t" + i + ". " + signerInfos[i] + "\n"); 793 } 794 return out; 795 } 796 797 /** 798 * Returns true if this is a JDK1.1.x-style PKCS#7 block, and false 799 * otherwise. 800 */ isOldStyle()801 public boolean isOldStyle() { 802 return this.oldStyle; 803 } 804 805 // BEGIN Android-added 806 /** 807 * For legacy reasons we need to return exactly the original encoded certificate bytes, instead 808 * of letting the underlying implementation have a shot at re-encoding the data. 809 */ 810 private static class VerbatimX509Certificate extends WrappedX509Certificate { 811 private byte[] encodedVerbatim; 812 VerbatimX509Certificate(X509Certificate wrapped, byte[] encodedVerbatim)813 public VerbatimX509Certificate(X509Certificate wrapped, byte[] encodedVerbatim) { 814 super(wrapped); 815 this.encodedVerbatim = encodedVerbatim; 816 } 817 818 @Override getEncoded()819 public byte[] getEncoded() throws CertificateEncodingException { 820 return encodedVerbatim; 821 } 822 } 823 824 private static class WrappedX509Certificate extends X509Certificate { 825 private final X509Certificate wrapped; 826 WrappedX509Certificate(X509Certificate wrapped)827 public WrappedX509Certificate(X509Certificate wrapped) { 828 this.wrapped = wrapped; 829 } 830 831 @Override getCriticalExtensionOIDs()832 public Set<String> getCriticalExtensionOIDs() { 833 return wrapped.getCriticalExtensionOIDs(); 834 } 835 836 @Override getExtensionValue(String oid)837 public byte[] getExtensionValue(String oid) { 838 return wrapped.getExtensionValue(oid); 839 } 840 841 @Override getNonCriticalExtensionOIDs()842 public Set<String> getNonCriticalExtensionOIDs() { 843 return wrapped.getNonCriticalExtensionOIDs(); 844 } 845 846 @Override hasUnsupportedCriticalExtension()847 public boolean hasUnsupportedCriticalExtension() { 848 return wrapped.hasUnsupportedCriticalExtension(); 849 } 850 851 @Override checkValidity()852 public void checkValidity() 853 throws CertificateExpiredException, CertificateNotYetValidException { 854 wrapped.checkValidity(); 855 } 856 857 @Override checkValidity(Date date)858 public void checkValidity(Date date) 859 throws CertificateExpiredException, CertificateNotYetValidException { 860 wrapped.checkValidity(date); 861 } 862 863 @Override getVersion()864 public int getVersion() { 865 return wrapped.getVersion(); 866 } 867 868 @Override getSerialNumber()869 public BigInteger getSerialNumber() { 870 return wrapped.getSerialNumber(); 871 } 872 873 @Override getIssuerDN()874 public Principal getIssuerDN() { 875 return wrapped.getIssuerDN(); 876 } 877 878 @Override getSubjectDN()879 public Principal getSubjectDN() { 880 return wrapped.getSubjectDN(); 881 } 882 883 @Override getNotBefore()884 public Date getNotBefore() { 885 return wrapped.getNotBefore(); 886 } 887 888 @Override getNotAfter()889 public Date getNotAfter() { 890 return wrapped.getNotAfter(); 891 } 892 893 @Override getTBSCertificate()894 public byte[] getTBSCertificate() throws CertificateEncodingException { 895 return wrapped.getTBSCertificate(); 896 } 897 898 @Override getSignature()899 public byte[] getSignature() { 900 return wrapped.getSignature(); 901 } 902 903 @Override getSigAlgName()904 public String getSigAlgName() { 905 return wrapped.getSigAlgName(); 906 } 907 908 @Override getSigAlgOID()909 public String getSigAlgOID() { 910 return wrapped.getSigAlgOID(); 911 } 912 913 @Override getSigAlgParams()914 public byte[] getSigAlgParams() { 915 return wrapped.getSigAlgParams(); 916 } 917 918 @Override getIssuerUniqueID()919 public boolean[] getIssuerUniqueID() { 920 return wrapped.getIssuerUniqueID(); 921 } 922 923 @Override getSubjectUniqueID()924 public boolean[] getSubjectUniqueID() { 925 return wrapped.getSubjectUniqueID(); 926 } 927 928 @Override getKeyUsage()929 public boolean[] getKeyUsage() { 930 return wrapped.getKeyUsage(); 931 } 932 933 @Override getBasicConstraints()934 public int getBasicConstraints() { 935 return wrapped.getBasicConstraints(); 936 } 937 938 @Override getEncoded()939 public byte[] getEncoded() throws CertificateEncodingException { 940 return wrapped.getEncoded(); 941 } 942 943 @Override verify(PublicKey key)944 public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException, 945 InvalidKeyException, NoSuchProviderException, SignatureException { 946 wrapped.verify(key); 947 } 948 949 @Override verify(PublicKey key, String sigProvider)950 public void verify(PublicKey key, String sigProvider) 951 throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, 952 NoSuchProviderException, SignatureException { 953 wrapped.verify(key, sigProvider); 954 } 955 956 @Override toString()957 public String toString() { 958 return wrapped.toString(); 959 } 960 961 @Override getPublicKey()962 public PublicKey getPublicKey() { 963 return wrapped.getPublicKey(); 964 } 965 966 @Override getExtendedKeyUsage()967 public List<String> getExtendedKeyUsage() throws CertificateParsingException { 968 return wrapped.getExtendedKeyUsage(); 969 } 970 971 @Override getIssuerAlternativeNames()972 public Collection<List<?>> getIssuerAlternativeNames() throws CertificateParsingException { 973 return wrapped.getIssuerAlternativeNames(); 974 } 975 976 @Override getIssuerX500Principal()977 public X500Principal getIssuerX500Principal() { 978 return wrapped.getIssuerX500Principal(); 979 } 980 981 @Override getSubjectAlternativeNames()982 public Collection<List<?>> getSubjectAlternativeNames() throws CertificateParsingException { 983 return wrapped.getSubjectAlternativeNames(); 984 } 985 986 @Override getSubjectX500Principal()987 public X500Principal getSubjectX500Principal() { 988 return wrapped.getSubjectX500Principal(); 989 } 990 991 @Override verify(PublicKey key, Provider sigProvider)992 public void verify(PublicKey key, Provider sigProvider) throws CertificateException, 993 NoSuchAlgorithmException, InvalidKeyException, SignatureException { 994 wrapped.verify(key, sigProvider); 995 } 996 } 997 // END Android-added 998 999 // BEGIN Android-removed: unused in Android 1000 /** 1001 * Assembles a PKCS #7 signed data message that optionally includes a 1002 * signature timestamp. 1003 * 1004 * @param signature the signature bytes 1005 * @param signerChain the signer's X.509 certificate chain 1006 * @param content the content that is signed; specify null to not include 1007 * it in the PKCS7 data 1008 * @param signatureAlgorithm the name of the signature algorithm 1009 * @param tsaURI the URI of the Timestamping Authority; or null if no 1010 * timestamp is requested 1011 * @param tSAPolicyID the TSAPolicyID of the Timestamping Authority as a 1012 * numerical object identifier; or null if we leave the TSA server 1013 * to choose one. This argument is only used when tsaURI is provided 1014 * @return the bytes of the encoded PKCS #7 signed data message 1015 * @throws NoSuchAlgorithmException The exception is thrown if the signature 1016 * algorithm is unrecognised. 1017 * @throws CertificateException The exception is thrown if an error occurs 1018 * while processing the signer's certificate or the TSA's 1019 * certificate. 1020 * @throws IOException The exception is thrown if an error occurs while 1021 * generating the signature timestamp or while generating the signed 1022 * data message. 1023 * 1024 public static byte[] generateSignedData(byte[] signature, 1025 X509Certificate[] signerChain, 1026 byte[] content, 1027 String signatureAlgorithm, 1028 URI tsaURI, 1029 String tSAPolicyID, 1030 String tSADigestAlg) 1031 throws CertificateException, IOException, NoSuchAlgorithmException 1032 { 1033 1034 // Generate the timestamp token 1035 PKCS9Attributes unauthAttrs = null; 1036 if (tsaURI != null) { 1037 // Timestamp the signature 1038 HttpTimestamper tsa = new HttpTimestamper(tsaURI); 1039 byte[] tsToken = generateTimestampToken( 1040 tsa, tSAPolicyID, tSADigestAlg, signature); 1041 1042 // Insert the timestamp token into the PKCS #7 signer info element 1043 // (as an unsigned attribute) 1044 unauthAttrs = 1045 new PKCS9Attributes(new PKCS9Attribute[]{ 1046 new PKCS9Attribute( 1047 PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_STR, 1048 tsToken)}); 1049 } 1050 1051 // Create the SignerInfo 1052 X500Name issuerName = 1053 X500Name.asX500Name(signerChain[0].getIssuerX500Principal()); 1054 BigInteger serialNumber = signerChain[0].getSerialNumber(); 1055 String encAlg = AlgorithmId.getEncAlgFromSigAlg(signatureAlgorithm); 1056 String digAlg = AlgorithmId.getDigAlgFromSigAlg(signatureAlgorithm); 1057 SignerInfo signerInfo = new SignerInfo(issuerName, serialNumber, 1058 AlgorithmId.get(digAlg), null, 1059 AlgorithmId.get(encAlg), 1060 signature, unauthAttrs); 1061 1062 // Create the PKCS #7 signed data message 1063 SignerInfo[] signerInfos = {signerInfo}; 1064 AlgorithmId[] algorithms = {signerInfo.getDigestAlgorithmId()}; 1065 // Include or exclude content 1066 ContentInfo contentInfo = (content == null) 1067 ? new ContentInfo(ContentInfo.DATA_OID, null) 1068 : new ContentInfo(content); 1069 PKCS7 pkcs7 = new PKCS7(algorithms, contentInfo, 1070 signerChain, signerInfos); 1071 ByteArrayOutputStream p7out = new ByteArrayOutputStream(); 1072 pkcs7.encodeSignedData(p7out); 1073 1074 return p7out.toByteArray(); 1075 } 1076 1077 /** 1078 * Requests, processes and validates a timestamp token from a TSA using 1079 * common defaults. Uses the following defaults in the timestamp request: 1080 * SHA-1 for the hash algorithm, a 64-bit nonce, and request certificate 1081 * set to true. 1082 * 1083 * @param tsa the timestamping authority to use 1084 * @param tSAPolicyID the TSAPolicyID of the Timestamping Authority as a 1085 * numerical object identifier; or null if we leave the TSA server 1086 * to choose one 1087 * @param toBeTimestamped the token that is to be timestamped 1088 * @return the encoded timestamp token 1089 * @throws IOException The exception is thrown if an error occurs while 1090 * communicating with the TSA, or a non-null 1091 * TSAPolicyID is specified in the request but it 1092 * does not match the one in the reply 1093 * @throws CertificateException The exception is thrown if the TSA's 1094 * certificate is not permitted for timestamping. 1095 * 1096 private static byte[] generateTimestampToken(Timestamper tsa, 1097 String tSAPolicyID, 1098 String tSADigestAlg, 1099 byte[] toBeTimestamped) 1100 throws IOException, CertificateException 1101 { 1102 // Generate a timestamp 1103 MessageDigest messageDigest = null; 1104 TSRequest tsQuery = null; 1105 try { 1106 messageDigest = MessageDigest.getInstance(tSADigestAlg); 1107 tsQuery = new TSRequest(tSAPolicyID, toBeTimestamped, messageDigest); 1108 } catch (NoSuchAlgorithmException e) { 1109 throw new IllegalArgumentException(e); 1110 } 1111 1112 // Generate a nonce 1113 BigInteger nonce = null; 1114 if (SecureRandomHolder.RANDOM != null) { 1115 nonce = new BigInteger(64, SecureRandomHolder.RANDOM); 1116 tsQuery.setNonce(nonce); 1117 } 1118 tsQuery.requestCertificate(true); 1119 1120 TSResponse tsReply = tsa.generateTimestamp(tsQuery); 1121 int status = tsReply.getStatusCode(); 1122 // Handle TSP error 1123 if (status != 0 && status != 1) { 1124 throw new IOException("Error generating timestamp: " + 1125 tsReply.getStatusCodeAsText() + " " + 1126 tsReply.getFailureCodeAsText()); 1127 } 1128 1129 if (tSAPolicyID != null && 1130 !tSAPolicyID.equals(tsReply.getTimestampToken().getPolicyID())) { 1131 throw new IOException("TSAPolicyID changed in " 1132 + "timestamp token"); 1133 } 1134 PKCS7 tsToken = tsReply.getToken(); 1135 1136 TimestampToken tst = tsReply.getTimestampToken(); 1137 try { 1138 if (!tst.getHashAlgorithm().equals(AlgorithmId.get(tSADigestAlg))) { 1139 throw new IOException("Digest algorithm not " + tSADigestAlg + " in " 1140 + "timestamp token"); 1141 } 1142 } catch (NoSuchAlgorithmException nase) { 1143 throw new IllegalArgumentException(); // should have been caught before 1144 } 1145 if (!MessageDigest.isEqual(tst.getHashedMessage(), 1146 tsQuery.getHashedMessage())) { 1147 throw new IOException("Digest octets changed in timestamp token"); 1148 } 1149 1150 BigInteger replyNonce = tst.getNonce(); 1151 if (replyNonce == null && nonce != null) { 1152 throw new IOException("Nonce missing in timestamp token"); 1153 } 1154 if (replyNonce != null && !replyNonce.equals(nonce)) { 1155 throw new IOException("Nonce changed in timestamp token"); 1156 } 1157 1158 // Examine the TSA's certificate (if present) 1159 for (SignerInfo si: tsToken.getSignerInfos()) { 1160 X509Certificate cert = si.getCertificate(tsToken); 1161 if (cert == null) { 1162 // Error, we've already set tsRequestCertificate = true 1163 throw new CertificateException( 1164 "Certificate not included in timestamp token"); 1165 } else { 1166 if (!cert.getCriticalExtensionOIDs().contains( 1167 EXTENDED_KEY_USAGE_OID)) { 1168 throw new CertificateException( 1169 "Certificate is not valid for timestamping"); 1170 } 1171 List<String> keyPurposes = cert.getExtendedKeyUsage(); 1172 if (keyPurposes == null || 1173 !keyPurposes.contains(KP_TIMESTAMPING_OID)) { 1174 throw new CertificateException( 1175 "Certificate is not valid for timestamping"); 1176 } 1177 } 1178 } 1179 return tsReply.getEncodedToken(); 1180 } 1181 */ 1182 // END Android-removed: unused in Android 1183 } 1184