• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
26 package sun.security.pkcs;
27 
28 import java.io.*;
29 
30 import sun.security.util.*;
31 
32 /**
33  * A ContentInfo type, as defined in PKCS#7.
34  *
35  * @author Benjamin Renaud
36  */
37 public class ContentInfo {
38 
39     // pkcs7 pre-defined content types
40     private static int[]  pkcs7 = {1, 2, 840, 113549, 1, 7};
41     private static int[]   data = {1, 2, 840, 113549, 1, 7, 1};
42     private static int[]  sdata = {1, 2, 840, 113549, 1, 7, 2};
43     private static int[]  edata = {1, 2, 840, 113549, 1, 7, 3};
44     private static int[] sedata = {1, 2, 840, 113549, 1, 7, 4};
45     private static int[]  ddata = {1, 2, 840, 113549, 1, 7, 5};
46     private static int[] crdata = {1, 2, 840, 113549, 1, 7, 6};
47     private static int[] nsdata = {2, 16, 840, 1, 113730, 2, 5};
48     // timestamp token (id-ct-TSTInfo) from RFC 3161
49     private static int[] tstInfo = {1, 2, 840, 113549, 1, 9, 16, 1, 4};
50     // this is for backwards-compatibility with JDK 1.1.x
51     private static final int[] OLD_SDATA = {1, 2, 840, 1113549, 1, 7, 2};
52     private static final int[] OLD_DATA = {1, 2, 840, 1113549, 1, 7, 1};
53     public static ObjectIdentifier PKCS7_OID;
54     public static ObjectIdentifier DATA_OID;
55     public static ObjectIdentifier SIGNED_DATA_OID;
56     public static ObjectIdentifier ENVELOPED_DATA_OID;
57     public static ObjectIdentifier SIGNED_AND_ENVELOPED_DATA_OID;
58     public static ObjectIdentifier DIGESTED_DATA_OID;
59     public static ObjectIdentifier ENCRYPTED_DATA_OID;
60     public static ObjectIdentifier OLD_SIGNED_DATA_OID;
61     public static ObjectIdentifier OLD_DATA_OID;
62     public static ObjectIdentifier NETSCAPE_CERT_SEQUENCE_OID;
63     public static ObjectIdentifier TIMESTAMP_TOKEN_INFO_OID;
64 
65     static {
66         PKCS7_OID =  ObjectIdentifier.newInternal(pkcs7);
67         DATA_OID = ObjectIdentifier.newInternal(data);
68         SIGNED_DATA_OID = ObjectIdentifier.newInternal(sdata);
69         ENVELOPED_DATA_OID = ObjectIdentifier.newInternal(edata);
70         SIGNED_AND_ENVELOPED_DATA_OID = ObjectIdentifier.newInternal(sedata);
71         DIGESTED_DATA_OID = ObjectIdentifier.newInternal(ddata);
72         ENCRYPTED_DATA_OID = ObjectIdentifier.newInternal(crdata);
73         OLD_SIGNED_DATA_OID = ObjectIdentifier.newInternal(OLD_SDATA);
74         OLD_DATA_OID = ObjectIdentifier.newInternal(OLD_DATA);
75         /**
76          * The ASN.1 systax for the Netscape Certificate Sequence
77          * data type is defined
78          * <a href=http://wp.netscape.com/eng/security/comm4-cert-download.html>
79          * here.</a>
80          */
81         NETSCAPE_CERT_SEQUENCE_OID = ObjectIdentifier.newInternal(nsdata);
82         TIMESTAMP_TOKEN_INFO_OID = ObjectIdentifier.newInternal(tstInfo);
83     }
84 
85     ObjectIdentifier contentType;
86     DerValue content; // OPTIONAL
87 
ContentInfo(ObjectIdentifier contentType, DerValue content)88     public ContentInfo(ObjectIdentifier contentType, DerValue content) {
89         this.contentType = contentType;
90         this.content = content;
91     }
92 
93     /**
94      * Make a contentInfo of type data.
95      */
ContentInfo(byte[] bytes)96     public ContentInfo(byte[] bytes) {
97         DerValue octetString = new DerValue(DerValue.tag_OctetString, bytes);
98         this.contentType = DATA_OID;
99         this.content = octetString;
100     }
101 
102     /**
103      * Parses a PKCS#7 content info.
104      */
ContentInfo(DerInputStream derin)105     public ContentInfo(DerInputStream derin)
106         throws IOException, ParsingException
107     {
108         this(derin, false);
109     }
110 
111     /**
112      * Parses a PKCS#7 content info.
113      *
114      * <p>This constructor is used only for backwards compatibility with
115      * PKCS#7 blocks that were generated using JDK1.1.x.
116      *
117      * @param derin the ASN.1 encoding of the content info.
118      * @param oldStyle flag indicating whether or not the given content info
119      * is encoded according to JDK1.1.x.
120      */
ContentInfo(DerInputStream derin, boolean oldStyle)121     public ContentInfo(DerInputStream derin, boolean oldStyle)
122         throws IOException, ParsingException
123     {
124         DerInputStream disType;
125         DerInputStream disTaggedContent;
126         DerValue type;
127         DerValue taggedContent;
128         DerValue[] typeAndContent;
129         DerValue[] contents;
130 
131         typeAndContent = derin.getSequence(2);
132 
133         // Parse the content type
134         type = typeAndContent[0];
135         disType = new DerInputStream(type.toByteArray());
136         contentType = disType.getOID();
137 
138         if (oldStyle) {
139             // JDK1.1.x-style encoding
140             content = typeAndContent[1];
141         } else {
142             // This is the correct, standards-compliant encoding.
143             // Parse the content (OPTIONAL field).
144             // Skip the [0] EXPLICIT tag by pretending that the content is the
145             // one and only element in an implicitly tagged set
146             if (typeAndContent.length > 1) { // content is OPTIONAL
147                 taggedContent = typeAndContent[1];
148                 disTaggedContent
149                     = new DerInputStream(taggedContent.toByteArray());
150                 contents = disTaggedContent.getSet(1, true);
151                 content = contents[0];
152             }
153         }
154     }
155 
getContent()156     public DerValue getContent() {
157         return content;
158     }
159 
getContentType()160     public ObjectIdentifier getContentType() {
161         return contentType;
162     }
163 
getData()164     public byte[] getData() throws IOException {
165         if (contentType.equals((Object)DATA_OID) ||
166             contentType.equals((Object)OLD_DATA_OID) ||
167             contentType.equals((Object)TIMESTAMP_TOKEN_INFO_OID)) {
168             if (content == null)
169                 return null;
170             else
171                 return content.getOctetString();
172         }
173         throw new IOException("content type is not DATA: " + contentType);
174     }
175 
encode(DerOutputStream out)176     public void encode(DerOutputStream out) throws IOException {
177         DerOutputStream contentDerCode;
178         DerOutputStream seq;
179 
180         seq = new DerOutputStream();
181         seq.putOID(contentType);
182 
183         // content is optional, it could be external
184         if (content != null) {
185             DerValue taggedContent = null;
186             contentDerCode = new DerOutputStream();
187             content.encode(contentDerCode);
188 
189             // Add the [0] EXPLICIT tag in front of the content encoding
190             taggedContent = new DerValue((byte)0xA0,
191                                          contentDerCode.toByteArray());
192             seq.putDerValue(taggedContent);
193         }
194 
195         out.write(DerValue.tag_Sequence, seq);
196     }
197 
198     /**
199      * Returns a byte array representation of the data held in
200      * the content field.
201      * @return             byte array representation of data held in content field
202      * @throws IOException if content bytes are invalid
203      */
getContentBytes()204     public byte[] getContentBytes() throws IOException {
205         if (content == null)
206             return null;
207 
208         DerInputStream dis = new DerInputStream(content.toByteArray());
209         return dis.getOctetString();
210     }
211 
toString()212     public String toString() {
213         String out = "";
214 
215         out += "Content Info Sequence\n\tContent type: " + contentType + "\n";
216         out += "\tContent: " + content;
217         return out;
218     }
219 }
220