001: /*
002: * @(#)ContentInfo.java 1.26 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package sun.security.pkcs;
029:
030: import java.io.*;
031:
032: import sun.security.util.*;
033:
034: /**
035: * A ContentInfo type, as defined in PKCS#7.
036: *
037: * @version 1.19
038: * @author Benjamin Renaud
039: */
040:
041: public class ContentInfo {
042:
043: // pkcs7 pre-defined content types
044: private static int[] pkcs7 = { 1, 2, 840, 113549, 1, 7 };
045: private static int[] data = { 1, 2, 840, 113549, 1, 7, 1 };
046: private static int[] sdata = { 1, 2, 840, 113549, 1, 7, 2 };
047: private static int[] edata = { 1, 2, 840, 113549, 1, 7, 3 };
048: private static int[] sedata = { 1, 2, 840, 113549, 1, 7, 4 };
049: private static int[] ddata = { 1, 2, 840, 113549, 1, 7, 5 };
050: private static int[] crdata = { 1, 2, 840, 113549, 1, 7, 6 };
051: private static int[] nsdata = { 2, 16, 840, 1, 113730, 2, 5 };
052: // this is for backwards-compatibility with JDK 1.1.x
053: private static final int[] OLD_SDATA = { 1, 2, 840, 1113549, 1, 7,
054: 2 };
055: private static final int[] OLD_DATA = { 1, 2, 840, 1113549, 1, 7, 1 };
056: public static ObjectIdentifier PKCS7_OID;
057: public static ObjectIdentifier DATA_OID;
058: public static ObjectIdentifier SIGNED_DATA_OID;
059: public static ObjectIdentifier ENVELOPED_DATA_OID;
060: public static ObjectIdentifier SIGNED_AND_ENVELOPED_DATA_OID;
061: public static ObjectIdentifier DIGESTED_DATA_OID;
062: public static ObjectIdentifier ENCRYPTED_DATA_OID;
063: public static ObjectIdentifier OLD_SIGNED_DATA_OID;
064: public static ObjectIdentifier OLD_DATA_OID;
065: public static ObjectIdentifier NETSCAPE_CERT_SEQUENCE_OID;
066:
067: static {
068: try {
069: PKCS7_OID = new ObjectIdentifier(pkcs7);
070: DATA_OID = new ObjectIdentifier(data);
071: SIGNED_DATA_OID = new ObjectIdentifier(sdata);
072: ENVELOPED_DATA_OID = new ObjectIdentifier(edata);
073: SIGNED_AND_ENVELOPED_DATA_OID = new ObjectIdentifier(sedata);
074: DIGESTED_DATA_OID = new ObjectIdentifier(ddata);
075: ENCRYPTED_DATA_OID = new ObjectIdentifier(crdata);
076: OLD_SIGNED_DATA_OID = new ObjectIdentifier(OLD_SDATA);
077: OLD_DATA_OID = new ObjectIdentifier(OLD_DATA);
078: /**
079: * The ASN.1 systax for the Netscape Certificate Sequence
080: * data type is defined
081: * <a href=http://www.netscape.com/eng/security/comm4-cert-download.html>
082: * here.</a>
083: */
084: NETSCAPE_CERT_SEQUENCE_OID = new ObjectIdentifier(nsdata);
085: } catch (IOException ioe) {
086: // should not happen
087: }
088: }
089:
090: ObjectIdentifier contentType;
091: DerValue content; // OPTIONAL
092:
093: public ContentInfo(ObjectIdentifier contentType, DerValue content) {
094: this .contentType = contentType;
095: this .content = content;
096: }
097:
098: /**
099: * Make a contentInfo of type data.
100: */
101: public ContentInfo(byte[] bytes) {
102: DerValue octetString = new DerValue(DerValue.tag_OctetString,
103: bytes);
104: this .contentType = DATA_OID;
105: this .content = octetString;
106: }
107:
108: /**
109: * Parses a PKCS#7 content info.
110: */
111: public ContentInfo(DerInputStream derin) throws IOException,
112: ParsingException {
113: this (derin, false);
114: }
115:
116: /**
117: * Parses a PKCS#7 content info.
118: *
119: * <p>This constructor is used only for backwards compatibility with
120: * PKCS#7 blocks that were generated using JDK1.1.x.
121: *
122: * @param derin the ASN.1 encoding of the content info.
123: * @param oldStyle flag indicating whether or not the given content info
124: * is encoded according to JDK1.1.x.
125: */
126: public ContentInfo(DerInputStream derin, boolean oldStyle)
127: throws IOException, ParsingException {
128: DerInputStream disType;
129: DerInputStream disTaggedContent;
130: DerValue type;
131: DerValue taggedContent;
132: DerValue[] typeAndContent;
133: DerValue[] contents;
134:
135: typeAndContent = derin.getSequence(2);
136:
137: // Parse the content type
138: type = typeAndContent[0];
139: disType = new DerInputStream(type.toByteArray());
140: contentType = disType.getOID();
141:
142: if (oldStyle) {
143: // JDK1.1.x-style encoding
144: content = typeAndContent[1];
145: } else {
146: // This is the correct, standards-compliant encoding.
147: // Parse the content (OPTIONAL field).
148: // Skip the [0] EXPLICIT tag by pretending that the content is the
149: // one and only element in an implicitly tagged set
150: if (typeAndContent.length > 1) { // content is OPTIONAL
151: taggedContent = typeAndContent[1];
152: disTaggedContent = new DerInputStream(taggedContent
153: .toByteArray());
154: contents = disTaggedContent.getSet(1, true);
155: content = contents[0];
156: }
157: }
158: }
159:
160: public DerValue getContent() {
161: return content;
162: }
163:
164: public ObjectIdentifier getContentType() {
165: return contentType;
166: }
167:
168: public byte[] getData() throws IOException {
169: if (contentType.equals(DATA_OID)
170: || contentType.equals(OLD_DATA_OID)) {
171: if (content == null)
172: return null;
173: else
174: return content.getOctetString();
175: }
176: throw new IOException("content type is not DATA: "
177: + contentType);
178: }
179:
180: public void encode(DerOutputStream out) throws IOException {
181: DerOutputStream contentDerCode;
182: DerOutputStream seq;
183:
184: seq = new DerOutputStream();
185: seq.putOID(contentType);
186:
187: // content is optional, it could be external
188: if (content != null) {
189: DerValue taggedContent = null;
190: contentDerCode = new DerOutputStream();
191: content.encode(contentDerCode);
192:
193: // Add the [0] EXPLICIT tag in front of the content encoding
194: taggedContent = new DerValue((byte) 0xA0, contentDerCode
195: .toByteArray());
196: seq.putDerValue(taggedContent);
197: }
198:
199: out.write(DerValue.tag_Sequence, seq);
200: }
201:
202: /**
203: * Returns a byte array representation of the data held in
204: * the content field.
205: */
206: public byte[] getContentBytes() throws IOException {
207: if (content == null)
208: return null;
209:
210: DerInputStream dis = new DerInputStream(content.toByteArray());
211: return dis.getOctetString();
212: }
213:
214: public String toString() {
215: String out = "";
216:
217: out += "Content Info Sequence\n\tContent type: " + contentType
218: + "\n";
219: out += "\tContent: " + content;
220: return out;
221: }
222: }
|