• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
PKCS7(InputStream in)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      */
PKCS7(DerInputStream derin)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      */
PKCS7(byte[] bytes)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      */
parse(DerInputStream derin)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      */
parse(DerInputStream derin, boolean oldStyle)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      */
PKCS7(AlgorithmId[] digestAlgorithmIds, ContentInfo contentInfo, X509Certificate[] certificates, X509CRL[] crls, SignerInfo[] signerInfos)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 
PKCS7(AlgorithmId[] digestAlgorithmIds, ContentInfo contentInfo, X509Certificate[] certificates, SignerInfo[] signerInfos)200     public PKCS7(AlgorithmId[] digestAlgorithmIds,
201                  ContentInfo contentInfo,
202                  X509Certificate[] certificates,
203                  SignerInfo[] signerInfos) {
204         this(digestAlgorithmIds, contentInfo, certificates, null, signerInfos);
205     }
206 
parseNetscapeCertChain(DerValue val)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 
parseSignedData(DerValue val)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      */
parseOldSignedData(DerValue val)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      */
encodeSignedData(OutputStream out)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      */
encodeSignedData(DerOutputStream out)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      */
verify(SignerInfo info, byte[] bytes)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      */
verify(SignerInfo info, InputStream dataInputStream)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      */
verify(byte[] bytes)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      */
verify()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      */
getVersion()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      */
getDigestAlgorithmIds()634     public AlgorithmId[] getDigestAlgorithmIds() {
635         return  digestAlgorithmIds;
636     }
637 
638     /**
639      * Returns the content information specified in this PKCS7 block.
640      */
getContentInfo()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      */
getCertificates()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      */
getCRLs()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      */
getSignerInfos()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      */
getCertificate(BigInteger serial, X500Name issuerName)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      */
populateCertIssuerNames()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      */
toString()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      */
isOldStyle()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 
VerbatimX509Certificate(X509Certificate wrapped, byte[] encodedVerbatim)782         public VerbatimX509Certificate(X509Certificate wrapped, byte[] encodedVerbatim) {
783             super(wrapped);
784             this.encodedVerbatim = encodedVerbatim;
785         }
786 
787         @Override
getEncoded()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 
WrappedX509Certificate(X509Certificate wrapped)796         public WrappedX509Certificate(X509Certificate wrapped) {
797             this.wrapped = wrapped;
798         }
799 
800         @Override
getCriticalExtensionOIDs()801         public Set<String> getCriticalExtensionOIDs() {
802             return wrapped.getCriticalExtensionOIDs();
803         }
804 
805         @Override
getExtensionValue(String oid)806         public byte[] getExtensionValue(String oid) {
807             return wrapped.getExtensionValue(oid);
808         }
809 
810         @Override
getNonCriticalExtensionOIDs()811         public Set<String> getNonCriticalExtensionOIDs() {
812             return wrapped.getNonCriticalExtensionOIDs();
813         }
814 
815         @Override
hasUnsupportedCriticalExtension()816         public boolean hasUnsupportedCriticalExtension() {
817             return wrapped.hasUnsupportedCriticalExtension();
818         }
819 
820         @Override
checkValidity()821         public void checkValidity()
822                 throws CertificateExpiredException, CertificateNotYetValidException {
823             wrapped.checkValidity();
824         }
825 
826         @Override
checkValidity(Date date)827         public void checkValidity(Date date)
828                 throws CertificateExpiredException, CertificateNotYetValidException {
829             wrapped.checkValidity(date);
830         }
831 
832         @Override
getVersion()833         public int getVersion() {
834             return wrapped.getVersion();
835         }
836 
837         @Override
getSerialNumber()838         public BigInteger getSerialNumber() {
839             return wrapped.getSerialNumber();
840         }
841 
842         @Override
getIssuerDN()843         public Principal getIssuerDN() {
844             return wrapped.getIssuerDN();
845         }
846 
847         @Override
getSubjectDN()848         public Principal getSubjectDN() {
849             return wrapped.getSubjectDN();
850         }
851 
852         @Override
getNotBefore()853         public Date getNotBefore() {
854             return wrapped.getNotBefore();
855         }
856 
857         @Override
getNotAfter()858         public Date getNotAfter() {
859             return wrapped.getNotAfter();
860         }
861 
862         @Override
getTBSCertificate()863         public byte[] getTBSCertificate() throws CertificateEncodingException {
864             return wrapped.getTBSCertificate();
865         }
866 
867         @Override
getSignature()868         public byte[] getSignature() {
869             return wrapped.getSignature();
870         }
871 
872         @Override
getSigAlgName()873         public String getSigAlgName() {
874             return wrapped.getSigAlgName();
875         }
876 
877         @Override
getSigAlgOID()878         public String getSigAlgOID() {
879             return wrapped.getSigAlgOID();
880         }
881 
882         @Override
getSigAlgParams()883         public byte[] getSigAlgParams() {
884             return wrapped.getSigAlgParams();
885         }
886 
887         @Override
getIssuerUniqueID()888         public boolean[] getIssuerUniqueID() {
889             return wrapped.getIssuerUniqueID();
890         }
891 
892         @Override
getSubjectUniqueID()893         public boolean[] getSubjectUniqueID() {
894             return wrapped.getSubjectUniqueID();
895         }
896 
897         @Override
getKeyUsage()898         public boolean[] getKeyUsage() {
899             return wrapped.getKeyUsage();
900         }
901 
902         @Override
getBasicConstraints()903         public int getBasicConstraints() {
904             return wrapped.getBasicConstraints();
905         }
906 
907         @Override
getEncoded()908         public byte[] getEncoded() throws CertificateEncodingException {
909             return wrapped.getEncoded();
910         }
911 
912         @Override
verify(PublicKey key)913         public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException,
914                 InvalidKeyException, NoSuchProviderException, SignatureException {
915             wrapped.verify(key);
916         }
917 
918         @Override
verify(PublicKey key, String sigProvider)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
toString()926         public String toString() {
927             return wrapped.toString();
928         }
929 
930         @Override
getPublicKey()931         public PublicKey getPublicKey() {
932             return wrapped.getPublicKey();
933         }
934 
935         @Override
getExtendedKeyUsage()936         public List<String> getExtendedKeyUsage() throws CertificateParsingException {
937             return wrapped.getExtendedKeyUsage();
938         }
939 
940         @Override
getIssuerAlternativeNames()941         public Collection<List<?>> getIssuerAlternativeNames() throws CertificateParsingException {
942             return wrapped.getIssuerAlternativeNames();
943         }
944 
945         @Override
getIssuerX500Principal()946         public X500Principal getIssuerX500Principal() {
947             return wrapped.getIssuerX500Principal();
948         }
949 
950         @Override
getSubjectAlternativeNames()951         public Collection<List<?>> getSubjectAlternativeNames() throws CertificateParsingException {
952             return wrapped.getSubjectAlternativeNames();
953         }
954 
955         @Override
getSubjectX500Principal()956         public X500Principal getSubjectX500Principal() {
957             return wrapped.getSubjectX500Principal();
958         }
959 
960         @Override
verify(PublicKey key, Provider sigProvider)961         public void verify(PublicKey key, Provider sigProvider) throws CertificateException,
962                 NoSuchAlgorithmException, InvalidKeyException, SignatureException {
963             wrapped.verify(key, sigProvider);
964         }
965     }
966 }
967