History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/pkcs/PKCS7.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/pkcs/PKCS7.java+739−0
@@ -0,0 +1,739 @@
1/*
2 * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.security.pkcs;
27
28import java.io.*;
29import java.math.BigInteger;
30import java.util.*;
31import java.security.cert.X509Certificate;
32import java.security.cert.CertificateException;
33import java.security.cert.X509CRL;
34import java.security.cert.CRLException;
35import java.security.cert.CertificateFactory;
36import java.security.*;
37
38import sun.security.util.*;
39import sun.security.x509.AlgorithmId;
40import sun.security.x509.CertificateIssuerName;
41import sun.security.x509.X509CertImpl;
42import sun.security.x509.X509CertInfo;
43import sun.security.x509.X509CRLImpl;
44import sun.security.x509.X500Name;
45
46/**
47 * PKCS7 as defined in RSA Laboratories PKCS7 Technical Note. Profile
48 * Supports only <tt>SignedData</tt> ContentInfo
49 * type, where to the type of data signed is plain Data.
50 * For signedData, <tt>crls</tt>, <tt>attributes</tt> and
51 * PKCS#6 Extended Certificates are not supported.
52 *
53 * @author Benjamin Renaud
54 */
55public class PKCS7 {
56
57 private ObjectIdentifier contentType;
58
59 // the ASN.1 members for a signedData (and other) contentTypes
60 private BigInteger version = null;
61 private AlgorithmId[] digestAlgorithmIds = null;
62 private ContentInfo contentInfo = null;
63 private X509Certificate[] certificates = null;
64 private X509CRL[] crls = null;
65 private SignerInfo[] signerInfos = null;
66
67 private boolean oldStyle = false; // Is this JDK1.1.x-style?
68
69 private Principal[] certIssuerNames;
70
71 /**
72 * Unmarshals a PKCS7 block from its encoded form, parsing the
73 * encoded bytes from the InputStream.
74 *
75 * @param in an input stream holding at least one PKCS7 block.
76 * @exception ParsingException on parsing errors.
77 * @exception IOException on other errors.
78 */
79 public PKCS7(InputStream in) throws ParsingException, IOException {
80 DataInputStream dis = new DataInputStream(in);
81 byte[] data = new byte[dis.available()];
82 dis.readFully(data);
83
84 parse(new DerInputStream(data));
85 }
86
87 /**
88 * Unmarshals a PKCS7 block from its encoded form, parsing the
89 * encoded bytes from the DerInputStream.
90 *
91 * @param derin a DerInputStream holding at least one PKCS7 block.
92 * @exception ParsingException on parsing errors.
93 */
94 public PKCS7(DerInputStream derin) throws ParsingException {
95 parse(derin);
96 }
97
98 /**
99 * Unmarshals a PKCS7 block from its encoded form, parsing the
100 * encoded bytes.
101 *
102 * @param bytes the encoded bytes.
103 * @exception ParsingException on parsing errors.
104 */
105 public PKCS7(byte[] bytes) throws ParsingException {
106 try {
107 DerInputStream derin = new DerInputStream(bytes);
108 parse(derin);
109 } catch (IOException ioe1) {
110 ParsingException pe = new ParsingException(
111 "Unable to parse the encoded bytes");
112 pe.initCause(ioe1);
113 throw pe;
114 }
115 }
116
117 /*
118 * Parses a PKCS#7 block.
119 */
120 private void parse(DerInputStream derin)
121 throws ParsingException
122 {
123 try {
124 derin.mark(derin.available());
125 // try new (i.e., JDK1.2) style
126 parse(derin, false);
127 } catch (IOException ioe) {
128 try {
129 derin.reset();
130 // try old (i.e., JDK1.1.x) style
131 parse(derin, true);
132 oldStyle = true;
133 } catch (IOException ioe1) {
134 ParsingException pe = new ParsingException(
135 ioe1.getMessage());
136 pe.initCause(ioe1);
137 throw pe;
138 }
139 }
140 }
141
142 /**
143 * Parses a PKCS#7 block.
144 *
145 * @param derin the ASN.1 encoding of the PKCS#7 block.
146 * @param oldStyle flag indicating whether or not the given PKCS#7 block
147 * is encoded according to JDK1.1.x.
148 */
149 private void parse(DerInputStream derin, boolean oldStyle)
150 throws IOException
151 {
152 contentInfo = new ContentInfo(derin, oldStyle);
153 contentType = contentInfo.contentType;
154 DerValue content = contentInfo.getContent();
155
156 if (contentType.equals(ContentInfo.SIGNED_DATA_OID)) {
157 parseSignedData(content);
158 } else if (contentType.equals(ContentInfo.OLD_SIGNED_DATA_OID)) {
159 // This is for backwards compatibility with JDK 1.1.x
160 parseOldSignedData(content);
161 } else if (contentType.equals(ContentInfo.NETSCAPE_CERT_SEQUENCE_OID)){
162 parseNetscapeCertChain(content);
163 } else {
164 throw new ParsingException("content type " + contentType +
165 " not supported.");
166 }
167 }
168
169 /**
170 * Construct an initialized PKCS7 block.
171 *
172 * @param digestAlgorithmIds the message digest algorithm identifiers.
173 * @param contentInfo the content information.
174 * @param certificates an array of X.509 certificates.
175 * @param crls an array of CRLs
176 * @param signerInfos an array of signer information.
177 */
178 public PKCS7(AlgorithmId[] digestAlgorithmIds,
179 ContentInfo contentInfo,
180 X509Certificate[] certificates,
181 X509CRL[] crls,
182 SignerInfo[] signerInfos) {
183
184 version = BigInteger.ONE;
185 this.digestAlgorithmIds = digestAlgorithmIds;
186 this.contentInfo = contentInfo;
187 this.certificates = certificates;
188 this.crls = crls;
189 this.signerInfos = signerInfos;
190 }
191
192 public PKCS7(AlgorithmId[] digestAlgorithmIds,
193 ContentInfo contentInfo,
194 X509Certificate[] certificates,
195 SignerInfo[] signerInfos) {
196 this(digestAlgorithmIds, contentInfo, certificates, null, signerInfos);
197 }
198
199 private void parseNetscapeCertChain(DerValue val)
200 throws ParsingException, IOException {
201 DerInputStream dis = new DerInputStream(val.toByteArray());
202 DerValue[] contents = dis.getSequence(2);
203 certificates = new X509Certificate[contents.length];
204
205 CertificateFactory certfac = null;
206 try {
207 certfac = CertificateFactory.getInstance("X.509");
208 } catch (CertificateException ce) {
209 // do nothing
210 }
211
212 for (int i=0; i < contents.length; i++) {
213 ByteArrayInputStream bais = null;
214 try {
215 if (certfac == null)
216 certificates[i] = new X509CertImpl(contents[i]);
217 else {
218 byte[] encoded = contents[i].toByteArray();
219 bais = new ByteArrayInputStream(encoded);
220 certificates[i] =
221 (X509Certificate)certfac.generateCertificate(bais);
222 bais.close();
223 bais = null;
224 }
225 } catch (CertificateException ce) {
226 ParsingException pe = new ParsingException(ce.getMessage());
227 pe.initCause(ce);
228 throw pe;
229 } catch (IOException ioe) {
230 ParsingException pe = new ParsingException(ioe.getMessage());
231 pe.initCause(ioe);
232 throw pe;
233 } finally {
234 if (bais != null)
235 bais.close();
236 }
237 }
238 }
239
240 private void parseSignedData(DerValue val)
241 throws ParsingException, IOException {
242
243 DerInputStream dis = val.toDerInputStream();
244
245 // Version
246 version = dis.getBigInteger();
247
248 // digestAlgorithmIds
249 DerValue[] digestAlgorithmIdVals = dis.getSet(1);
250 int len = digestAlgorithmIdVals.length;
251 digestAlgorithmIds = new AlgorithmId[len];
252 try {
253 for (int i = 0; i < len; i++) {
254 DerValue oid = digestAlgorithmIdVals[i];
255 digestAlgorithmIds[i] = AlgorithmId.parse(oid);
256 }
257
258 } catch (IOException e) {
259 ParsingException pe =
260 new ParsingException("Error parsing digest AlgorithmId IDs: " +
261 e.getMessage());
262 pe.initCause(e);
263 throw pe;
264 }
265 // contentInfo
266 contentInfo = new ContentInfo(dis);
267
268 CertificateFactory certfac = null;
269 try {
270 certfac = CertificateFactory.getInstance("X.509");
271 } catch (CertificateException ce) {
272 // do nothing
273 }
274
275 /*
276 * check if certificates (implicit tag) are provided
277 * (certificates are OPTIONAL)
278 */
279 if ((byte)(dis.peekByte()) == (byte)0xA0) {
280 DerValue[] certVals = dis.getSet(2, true);
281
282 len = certVals.length;
283 certificates = new X509Certificate[len];
284
285 for (int i = 0; i < len; i++) {
286 ByteArrayInputStream bais = null;
287 try {
288 if (certfac == null)
289 certificates[i] = new X509CertImpl(certVals[i]);
290 else {
291 byte[] encoded = certVals[i].toByteArray();
292 bais = new ByteArrayInputStream(encoded);
293 certificates[i] =
294 (X509Certificate)certfac.generateCertificate(bais);
295 bais.close();
296 bais = null;
297 }
298 } catch (CertificateException ce) {
299 ParsingException pe = new ParsingException(ce.getMessage());
300 pe.initCause(ce);
301 throw pe;
302 } catch (IOException ioe) {
303 ParsingException pe = new ParsingException(ioe.getMessage());
304 pe.initCause(ioe);
305 throw pe;
306 } finally {
307 if (bais != null)
308 bais.close();
309 }
310 }
311 }
312
313 // check if crls (implicit tag) are provided (crls are OPTIONAL)
314 if ((byte)(dis.peekByte()) == (byte)0xA1) {
315 DerValue[] crlVals = dis.getSet(1, true);
316
317 len = crlVals.length;
318 crls = new X509CRL[len];
319
320 for (int i = 0; i < len; i++) {
321 ByteArrayInputStream bais = null;
322 try {
323 if (certfac == null)
324 crls[i] = new X509CRLImpl(crlVals[i]);
325 else {
326 byte[] encoded = crlVals[i].toByteArray();
327 bais = new ByteArrayInputStream(encoded);
328 crls[i] = (X509CRL) certfac.generateCRL(bais);
329 bais.close();
330 bais = null;
331 }
332 } catch (CRLException e) {
333 ParsingException pe =
334 new ParsingException(e.getMessage());
335 pe.initCause(e);
336 throw pe;
337 } finally {
338 if (bais != null)
339 bais.close();
340 }
341 }
342 }
343
344 // signerInfos
345 DerValue[] signerInfoVals = dis.getSet(1);
346
347 len = signerInfoVals.length;
348 signerInfos = new SignerInfo[len];
349
350 for (int i = 0; i < len; i++) {
351 DerInputStream in = signerInfoVals[i].toDerInputStream();
352 signerInfos[i] = new SignerInfo(in);
353 }
354 }
355
356 /*
357 * Parses an old-style SignedData encoding (for backwards
358 * compatibility with JDK1.1.x).
359 */
360 private void parseOldSignedData(DerValue val)
361 throws ParsingException, IOException
362 {
363 DerInputStream dis = val.toDerInputStream();
364
365 // Version
366 version = dis.getBigInteger();
367
368 // digestAlgorithmIds
369 DerValue[] digestAlgorithmIdVals = dis.getSet(1);
370 int len = digestAlgorithmIdVals.length;
371
372 digestAlgorithmIds = new AlgorithmId[len];
373 try {
374 for (int i = 0; i < len; i++) {
375 DerValue oid = digestAlgorithmIdVals[i];
376 digestAlgorithmIds[i] = AlgorithmId.parse(oid);
377 }
378 } catch (IOException e) {
379 throw new ParsingException("Error parsing digest AlgorithmId IDs");
380 }
381
382 // contentInfo
383 contentInfo = new ContentInfo(dis, true);
384
385 // certificates
386 CertificateFactory certfac = null;
387 try {
388 certfac = CertificateFactory.getInstance("X.509");
389 } catch (CertificateException ce) {
390 // do nothing
391 }
392 DerValue[] certVals = dis.getSet(2);
393 len = certVals.length;
394 certificates = new X509Certificate[len];
395
396 for (int i = 0; i < len; i++) {
397 ByteArrayInputStream bais = null;
398 try {
399 if (certfac == null)
400 certificates[i] = new X509CertImpl(certVals[i]);
401 else {
402 byte[] encoded = certVals[i].toByteArray();
403 bais = new ByteArrayInputStream(encoded);
404 certificates[i] =
405 (X509Certificate)certfac.generateCertificate(bais);
406 bais.close();
407 bais = null;
408 }
409 } catch (CertificateException ce) {
410 ParsingException pe = new ParsingException(ce.getMessage());
411 pe.initCause(ce);
412 throw pe;
413 } catch (IOException ioe) {
414 ParsingException pe = new ParsingException(ioe.getMessage());
415 pe.initCause(ioe);
416 throw pe;
417 } finally {
418 if (bais != null)
419 bais.close();
420 }
421 }
422
423 // crls are ignored.
424 dis.getSet(0);
425
426 // signerInfos
427 DerValue[] signerInfoVals = dis.getSet(1);
428 len = signerInfoVals.length;
429 signerInfos = new SignerInfo[len];
430 for (int i = 0; i < len; i++) {
431 DerInputStream in = signerInfoVals[i].toDerInputStream();
432 signerInfos[i] = new SignerInfo(in, true);
433 }
434 }
435
436 /**
437 * Encodes the signed data to an output stream.
438 *
439 * @param out the output stream to write the encoded data to.
440 * @exception IOException on encoding errors.
441 */
442 public void encodeSignedData(OutputStream out) throws IOException {
443 DerOutputStream derout = new DerOutputStream();
444 encodeSignedData(derout);
445 out.write(derout.toByteArray());
446 }
447
448 /**
449 * Encodes the signed data to a DerOutputStream.
450 *
451 * @param out the DerOutputStream to write the encoded data to.
452 * @exception IOException on encoding errors.
453 */
454 public void encodeSignedData(DerOutputStream out)
455 throws IOException
456 {
457 DerOutputStream signedData = new DerOutputStream();
458
459 // version
460 signedData.putInteger(version);
461
462 // digestAlgorithmIds
463 signedData.putOrderedSetOf(DerValue.tag_Set, digestAlgorithmIds);
464
465 // contentInfo
466 contentInfo.encode(signedData);
467
468 // certificates (optional)
469 if (certificates != null && certificates.length != 0) {
470 // cast to X509CertImpl[] since X509CertImpl implements DerEncoder
471 X509CertImpl implCerts[] = new X509CertImpl[certificates.length];
472 for (int i = 0; i < certificates.length; i++) {
473 if (certificates[i] instanceof X509CertImpl)
474 implCerts[i] = (X509CertImpl) certificates[i];
475 else {
476 try {
477 byte[] encoded = certificates[i].getEncoded();
478 implCerts[i] = new X509CertImpl(encoded);
479 } catch (CertificateException ce) {
480 IOException ie = new IOException(ce.getMessage());
481 ie.initCause(ce);
482 throw ie;
483 }
484 }
485 }
486
487 // Add the certificate set (tagged with [0] IMPLICIT)
488 // to the signed data
489 signedData.putOrderedSetOf((byte)0xA0, implCerts);
490 }
491
492 // CRLs (optional)
493 if (crls != null && crls.length != 0) {
494 // cast to X509CRLImpl[] since X509CRLImpl implements DerEncoder
495 Set<X509CRLImpl> implCRLs = new HashSet<X509CRLImpl>(crls.length);
496 for (X509CRL crl: crls) {
497 if (crl instanceof X509CRLImpl)
498 implCRLs.add((X509CRLImpl) crl);
499 else {
500 try {
501 byte[] encoded = crl.getEncoded();
502 implCRLs.add(new X509CRLImpl(encoded));
503 } catch (CRLException ce) {
504 IOException ie = new IOException(ce.getMessage());
505 ie.initCause(ce);
506 throw ie;
507 }
508 }
509 }
510
511 // Add the CRL set (tagged with [1] IMPLICIT)
512 // to the signed data
513 signedData.putOrderedSetOf((byte)0xA1,
514 implCRLs.toArray(new X509CRLImpl[implCRLs.size()]));
515 }
516
517 // signerInfos
518 signedData.putOrderedSetOf(DerValue.tag_Set, signerInfos);
519
520 // making it a signed data block
521 DerValue signedDataSeq = new DerValue(DerValue.tag_Sequence,
522 signedData.toByteArray());
523
524 // making it a content info sequence
525 ContentInfo block = new ContentInfo(ContentInfo.SIGNED_DATA_OID,
526 signedDataSeq);
527
528 // writing out the contentInfo sequence
529 block.encode(out);
530 }
531
532 /**
533 * This verifies a given SignerInfo.
534 *
535 * @param info the signer information.
536 * @param bytes the DER encoded content information.
537 *
538 * @exception NoSuchAlgorithmException on unrecognized algorithms.
539 * @exception SignatureException on signature handling errors.
540 */
541 public SignerInfo verify(SignerInfo info, byte[] bytes)
542 throws NoSuchAlgorithmException, SignatureException {
543 return info.verify(this, bytes);
544 }
545
546 /**
547 * Returns all signerInfos which self-verify.
548 *
549 * @param bytes the DER encoded content information.
550 *
551 * @exception NoSuchAlgorithmException on unrecognized algorithms.
552 * @exception SignatureException on signature handling errors.
553 */
554 public SignerInfo[] verify(byte[] bytes)
555 throws NoSuchAlgorithmException, SignatureException {
556
557 Vector<SignerInfo> intResult = new Vector<SignerInfo>();
558 for (int i = 0; i < signerInfos.length; i++) {
559
560 SignerInfo signerInfo = verify(signerInfos[i], bytes);
561 if (signerInfo != null) {
562 intResult.addElement(signerInfo);
563 }
564 }
565 if (intResult.size() != 0) {
566
567 SignerInfo[] result = new SignerInfo[intResult.size()];
568 intResult.copyInto(result);
569 return result;
570 }
571 return null;
572 }
573
574 /**
575 * Returns all signerInfos which self-verify.
576 *
577 * @exception NoSuchAlgorithmException on unrecognized algorithms.
578 * @exception SignatureException on signature handling errors.
579 */
580 public SignerInfo[] verify()
581 throws NoSuchAlgorithmException, SignatureException {
582 return verify(null);
583 }
584
585 /**
586 * Returns the version number of this PKCS7 block.
587 * @return the version or null if version is not specified
588 * for the content type.
589 */
590 public BigInteger getVersion() {
591 return version;
592 }
593
594 /**
595 * Returns the message digest algorithms specified in this PKCS7 block.
596 * @return the array of Digest Algorithms or null if none are specified
597 * for the content type.
598 */
599 public AlgorithmId[] getDigestAlgorithmIds() {
600 return digestAlgorithmIds;
601 }
602
603 /**
604 * Returns the content information specified in this PKCS7 block.
605 */
606 public ContentInfo getContentInfo() {
607 return contentInfo;
608 }
609
610 /**
611 * Returns the X.509 certificates listed in this PKCS7 block.
612 * @return a clone of the array of X.509 certificates or null if
613 * none are specified for the content type.
614 */
615 public X509Certificate[] getCertificates() {
616 if (certificates != null)
617 return certificates.clone();
618 else
619 return null;
620 }
621
622 /**
623 * Returns the X.509 crls listed in this PKCS7 block.
624 * @return a clone of the array of X.509 crls or null if none
625 * are specified for the content type.
626 */
627 public X509CRL[] getCRLs() {
628 if (crls != null)
629 return crls.clone();
630 else
631 return null;
632 }
633
634 /**
635 * Returns the signer's information specified in this PKCS7 block.
636 * @return the array of Signer Infos or null if none are specified
637 * for the content type.
638 */
639 public SignerInfo[] getSignerInfos() {
640 return signerInfos;
641 }
642
643 /**
644 * Returns the X.509 certificate listed in this PKCS7 block
645 * which has a matching serial number and Issuer name, or
646 * null if one is not found.
647 *
648 * @param serial the serial number of the certificate to retrieve.
649 * @param issuerName the Distinguished Name of the Issuer.
650 */
651 public X509Certificate getCertificate(BigInteger serial, X500Name issuerName) {
652 if (certificates != null) {
653 if (certIssuerNames == null)
654 populateCertIssuerNames();
655 for (int i = 0; i < certificates.length; i++) {
656 X509Certificate cert = certificates[i];
657 BigInteger thisSerial = cert.getSerialNumber();
658 if (serial.equals(thisSerial)
659 && issuerName.equals(certIssuerNames[i]))
660 {
661 return cert;
662 }
663 }
664 }
665 return null;
666 }
667
668 /**
669 * Populate array of Issuer DNs from certificates and convert
670 * each Principal to type X500Name if necessary.
671 */
672 private void populateCertIssuerNames() {
673 if (certificates == null)
674 return;
675
676 certIssuerNames = new Principal[certificates.length];
677 for (int i = 0; i < certificates.length; i++) {
678 X509Certificate cert = certificates[i];
679 Principal certIssuerName = cert.getIssuerDN();
680 if (!(certIssuerName instanceof X500Name)) {
681 // must extract the original encoded form of DN for
682 // subsequent name comparison checks (converting to a
683 // String and back to an encoded DN could cause the
684 // types of String attribute values to be changed)
685 try {
686 X509CertInfo tbsCert =
687 new X509CertInfo(cert.getTBSCertificate());
688 certIssuerName = (Principal)
689 tbsCert.get(CertificateIssuerName.NAME + "." +
690 CertificateIssuerName.DN_NAME);
691 } catch (Exception e) {
692 // error generating X500Name object from the cert's
693 // issuer DN, leave name as is.
694 }
695 }
696 certIssuerNames[i] = certIssuerName;
697 }
698 }
699
700 /**
701 * Returns the PKCS7 block in a printable string form.
702 */
703 public String toString() {
704 String out = "";
705
706 out += contentInfo + "\n";
707 if (version != null)
708 out += "PKCS7 :: version: " + Debug.toHexString(version) + "\n";
709 if (digestAlgorithmIds != null) {
710 out += "PKCS7 :: digest AlgorithmIds: \n";
711 for (int i = 0; i < digestAlgorithmIds.length; i++)
712 out += "\t" + digestAlgorithmIds[i] + "\n";
713 }
714 if (certificates != null) {
715 out += "PKCS7 :: certificates: \n";
716 for (int i = 0; i < certificates.length; i++)
717 out += "\t" + i + ". " + certificates[i] + "\n";
718 }
719 if (crls != null) {
720 out += "PKCS7 :: crls: \n";
721 for (int i = 0; i < crls.length; i++)
722 out += "\t" + i + ". " + crls[i] + "\n";
723 }
724 if (signerInfos != null) {
725 out += "PKCS7 :: signer infos: \n";
726 for (int i = 0; i < signerInfos.length; i++)
727 out += ("\t" + i + ". " + signerInfos[i] + "\n");
728 }
729 return out;
730 }
731
732 /**
733 * Returns true if this is a JDK1.1.x-style PKCS#7 block, and false
734 * otherwise.
735 */
736 public boolean isOldStyle() {
737 return this.oldStyle;
738 }
739}