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